Skip to content

node_runtime: Tolerate non-string values in npm time metadata#57765

Merged
benbrandt merged 1 commit into
zed-industries:mainfrom
controversial:fix-npm-info-time-null
May 27, 2026
Merged

node_runtime: Tolerate non-string values in npm time metadata#57765
benbrandt merged 1 commit into
zed-industries:mainfrom
controversial:fix-npm-info-time-null

Conversation

@controversial

@controversial controversial commented May 27, 2026

Copy link
Copy Markdown
Contributor

Note

Authored by Claude, but fixes a real issue I encountered; I have reviewed the diff

Some npm registries return npm info --json with non-string values in the time map. JFrog Artifactory emits "unpublished": null, and npm itself represents unpublished as an object for packages that have had versions unpublished.

Because NpmInfo.time was typed HashMap<String, String>, serde aborted the entire deserialization with invalid type: null, expected a string. As a result select_npm_package_version never ran, and language servers installed via npm (for example the tsgo extension, tailwindcss-language-server, and json-language-server) failed to start with an error like:

Failed to start language server "tsgo": invalid type: null, expected a string at line 100 column 23

Only version keys in time are ever read (to honor npm's before cutoff), so this deserializes the map leniently: keep the string-valued entries and drop the rest. The field type and all downstream logic are unchanged. Added a regression test covering a time map containing "unpublished": null.

Self-Review Checklist:

  • I've reviewed my own diff for quality, security, and reliability
  • Unsafe blocks (if any) have justifying comments
  • The content is consistent with the UI/UX checklist
  • Tests cover the new/changed behavior
  • Performance impact has been considered and is acceptable

Release Notes:

  • Fixed language servers failing to install when the npm registry returns non-string values (such as "unpublished": null) in package time metadata

Some npm registries return `npm info --json` with non-string values in
the `time` map. JFrog Artifactory emits `"unpublished": null`, and npm
itself reports `unpublished` as an object once a package has had versions
unpublished. Because `NpmInfo.time` was typed `HashMap<String, String>`,
serde aborted deserialization with `invalid type: null, expected a
string`, so `select_npm_package_version` never ran and language servers
installed via npm failed to start.

Only version keys in `time` are read (to honor npm's `before` cutoff), so
deserialize it leniently: keep string-valued entries and drop the rest.
The field type and downstream logic are unchanged.
@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label May 27, 2026
@zed-community-bot zed-community-bot Bot added the first contribution the author's first pull request to Zed. NOTE: the label application is automated via github actions label May 27, 2026
@benbrandt

Copy link
Copy Markdown
Member

Thanks!

@benbrandt benbrandt enabled auto-merge May 27, 2026 04:30
@benbrandt benbrandt added this pull request to the merge queue May 27, 2026
Merged via the queue into zed-industries:main with commit e254582 May 27, 2026
45 checks passed
@controversial controversial deleted the fix-npm-info-time-null branch May 28, 2026 04:20
TomPlanche pushed a commit to TomPlanche/zed that referenced this pull request Jun 2, 2026
…dustries#57765)

> [!NOTE] 
> Authored by Claude, but fixes a real issue I encountered; I have
reviewed the diff

Some npm registries return `npm info --json` with non-string values in
the `time` map. JFrog Artifactory emits `"unpublished": null`, and npm
itself represents `unpublished` as an object for packages that have had
versions unpublished.

Because `NpmInfo.time` was typed `HashMap<String, String>`, serde
aborted the entire deserialization with `invalid type: null, expected a
string`. As a result `select_npm_package_version` never ran, and
language servers installed via npm (for example the tsgo extension,
`tailwindcss-language-server`, and `json-language-server`) failed to
start with an error like:

```
Failed to start language server "tsgo": invalid type: null, expected a string at line 100 column 23
```

Only version keys in `time` are ever read (to honor npm's `before`
cutoff), so this deserializes the map leniently: keep the string-valued
entries and drop the rest. The field type and all downstream logic are
unchanged. Added a regression test covering a `time` map containing
`"unpublished": null`.

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the UI/UX checklist
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Fixed language servers failing to install when the npm registry
returns non-string values (such as `"unpublished": null`) in package
`time` metadata
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement first contribution the author's first pull request to Zed. NOTE: the label application is automated via github actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants