Skip to content

Type incoming request ids as Int64, not Int (fixes 32-bit Julia) - #127

Merged
davidanthoff merged 2 commits into
mainfrom
crashfix/int64-request-ids
Oct 4, 2026
Merged

davidanthoff merged 2 commits into
mainfrom
crashfix/int64-request-ids

Conversation

@davidanthoff

@davidanthoff davidanthoff commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

This PR was opened by Claude (Claude Code) on David's behalf.

Problem

On 32-bit Julia, the julia-vscode language server dies on its first request. Crash telemetry has reported this since 1.219.2 (4 users, all i686-w64-mingw32):

JSONRPC.TransportError: Read task failed
  caused by: MethodError: Cannot `convert` an object of type Int64 to an object of type Union{Int32, String}
  at get_next_message (JSONRPC/src/core.jl:791)

The JSON parser returns integer request ids as Int64. The id-keyed slots were typed with Int, and on 32-bit Julia Int === Int32. convert(Union{Int32,String}, ::Int64) has no method (unlike Union{Nothing,Int32}, which convert handles), so x.cancellation_sources[id] = cancel_source in the read task threw, and the endpoint went to status_errored.

Fix

These three slots now use Int64 instead of Int:

  • Request.id
  • JSONRPCEndpoint.cancellation_sources
  • JSONRPCEndpoint.no_longer_needed_cancellation_sources

Other id handling I checked:

  • outstanding_requests is keyed by String, and our own outgoing ids are UUID strings. A response with an integer id is looked up with get, which does not convert, so an unknown integer id still gives the existing "unknown request id" TransportError, not a MethodError.
  • The $/cancelRequest lookup and the delete! of finished ids also use get/delete!, so neither converts.
  • send_success_response/send_error_response echo original_request.id back unchanged.
  • typed.jl and interface_def.jl only compare the id with nothing.

Tests

The new test/test_request_ids.jl has two test items:

  • The id field, dict key type and channel eltype accept an Int64 id outside the Int32 range, and the value goes through each of them unconverted.
  • End to end: a raw peer sends a request whose id is typemax(Int32) + 5 to a running endpoint, cancels it with $/cancelRequest, and gets the response back with the same Int64 id. A further message then confirms that the finished request's cancellation source was dropped and that the endpoint is still running. The waits time out, so on a broken build the test fails instead of hanging.

CI includes ~x86 (32-bit) legs, so the new tests guard against this from now on. Before pushing, I also ran the full suite locally with juliaup's 1.12~x86 channel (Sys.WORD_SIZE == 32):

32-bit Julia 1.12.7 64-bit Julia 1.12.7
main + new tests 608 passed, 6 failed, 2 errored, all in the new file. The end-to-end item hits the exact telemetry error: TransportError("Read task failed", MethodError(convert, (Union{Int32, String}, 2147483652))) not run
this PR 621/621 passed 621/621 passed

The first push used only, which needs Julia 1.4, so the 1.0–1.3 legs failed. The second commit replaces it, and the suite now passes locally on Julia 1.0.5 (622/622) and on 32-bit 1.12.7 (622/622).

On 64-bit Julia Int64 === Int, so this PR changes nothing there.

Downstream

This removes only the first 32-bit failure. Once the language server gets past its first request on 32-bit Julia, more failures of the same kind may show up downstream. A quick look shows protocol types that will fail the same way whenever a peer sends an integer:

  • LanguageServer.jl: the ProgressToken fields (workDoneToken/partialResultToken/token::Union{Int,String[,Missing]}). VS Code normally sends string tokens.
  • DebugAdapter.jl: src/protocol/types.jl (id::Union{Int,String}, moduleId::Union{Missing,Int,String}).

None of these have shown up in telemetry yet. They are not changed here.

🤖 Generated with Claude Code

The JSON parser returns integer request ids as Int64. On 32-bit Julia
`Int === Int32`, so storing the id of the very first incoming request in
`cancellation_sources` threw `MethodError: Cannot convert Int64 to
Union{Int32, String}`, which killed the read task with "Read task failed".
`Request.id` and `no_longer_needed_cancellation_sources` had the same
problem.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`only` needs Julia 1.4, and CI tests back to 1.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.46%. Comparing base (14e3bb5) to head (7b9fd4e).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #127      +/-   ##
==========================================
- Coverage   92.02%   91.46%   -0.56%     
==========================================
  Files           5        5              
  Lines         539      539              
==========================================
- Hits          496      493       -3     
- Misses         43       46       +3     
Flag Coverage Δ
unittests 91.46% <ø> (-0.56%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@davidanthoff
davidanthoff merged commit caa18a4 into main Oct 4, 2026
322 of 327 checks passed
@davidanthoff
davidanthoff deleted the crashfix/int64-request-ids branch October 4, 2026 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant