Skip to content

Handle Windows absolute paths for schema inputs#2886

Open
schani wants to merge 1 commit into
masterfrom
fix/windows-schema-paths
Open

Handle Windows absolute paths for schema inputs#2886
schani wants to merge 1 commit into
masterfrom
fix/windows-schema-paths

Conversation

@schani

@schani schani commented Jul 7, 2026

Copy link
Copy Markdown
Member

Problem

On Windows, giving quicktype a schema input as an absolute path fails:

quicktype -s schema C:\Users\Cat\...\bookmark.schema.json -o out.ts --just-types
Error: Could not fetch schema , referred to from c:\Users\Cat\...\bookmark.schema.json#items.

Schemas without relative $refs fail too, with Internal error: Defined value expected. Relative paths work.

Root cause

Schema addresses are parsed with urijs, and a Windows absolute path is not a valid URI: urijs parses the drive letter of C:\Users\me\top.schema.json as a URI scheme (lowercasing it, and keeping the backslashes as an opaque path). The mangled address breaks schema-store lookups, and relative $refs resolved against it via absoluteTo yield bogus addresses like c:///item.schema.json, which is-url in NodeIO then classifies as HTTP URLs and tries to fetch.

The fix

  • packages/quicktype-core/src/input/JSONSchemaInput.ts: a new fixWindowsPath helper converts Windows absolute paths (drive-letter C:\.../C:/... and UNC \\server\share\... forms) to file: URIs, applied at the three places where address strings are parsed into URIs (normalizeURI, Ref.root, Ref.parse). urijs handles file: URIs correctly, so normalization, schema-store keying, and relative-$ref resolution all work unchanged (drive-letter casing is preserved because the letter is now in the URI path, not the scheme).
  • packages/quicktype-core/src/input/io/NodeIO.ts: readableFromFileOrURL now reads file: URIs from disk instead of letting is-url classify them as HTTP URLs. Deliberately not url.fileURLToPath (its result is platform-dependent): a drive-letter URI maps to C:/dir/x.json, which is the correct absolute path on Windows (Node's fs accepts forward slashes there) and a cwd-relative path on POSIX, which is what makes the bug testable on Linux CI.

Plain POSIX paths never hit either code path, and other input kinds (JSON, GraphQL) don't go through the schema-address machinery at all.

Tests (written first)

test/check-windows-schema-paths.ts, run by test/test.ts before the fixtures in every CI job (same pattern as the #2850 check). It builds a literal C:/Users/quicktype/ directory tree in a temp dir, chdirs into it, and runs the quicktype-core pipeline (JSONSchemaInput + FetchingJSONSchemaStore, exactly as the CLI wires it) with three schema-path spellings, where the top-level schema $refs a sibling file so relative-ref resolution is asserted too:

  • Windows absolute path with backslashes
  • Windows absolute path with forward slashes
  • POSIX absolute path (guards against regressing existing behavior)

The check was added and run before the fix, failing with the issue's exact symptom on both Windows cases (POSIX case passed):

error: schema inputs given as absolute paths must work (issue #2869):
    Windows absolute path with backslashes: quicktype failed: Error: Internal error: Defined value expected, but got undefined
    Windows absolute path with forward slashes: quicktype failed: Error: Internal error: Defined value expected, but got undefined

After the fix it passes, and the issue's original command (simulated on Linux via a literal C:/Users/Cat/ tree, run as quicktype -s schema 'C:\Users\Cat\bookmark.schema.json' --lang typescript --just-types) now produces the same output as the relative-path invocation.

Verification notes

  • FIXTURE=schema-golang script/test on all 63 local schema samples: green. (ref-remote.schema was excluded — it fails identically on unmodified master in this environment because remote fetching via global.fetch doesn't work with the local getStream; CI swaps in cross-fetch via env.sh. Unrelated to this change.)
  • FIXTURE=golang on JSON priority samples: green (NodeIO's non-schema path unaffected).
  • Not verifiable locally: behavior on an actual Windows machine (no Windows CI job exists). The drive-letter and UNC → file: URI mappings follow the standard Windows file-URI convention, and the POSIX-side simulation exercises the full pipeline including $ref resolution.

Fixes #2869

🤖 Generated with Claude Code

Schema inputs given as Windows absolute paths (e.g.
"C:\Users\me\top.schema.json") failed with "Could not fetch schema ..."
or "Internal error: Defined value expected".

Root cause: schema addresses are parsed with urijs, which treats the
drive letter of a Windows absolute path as a URI *scheme* (lowercasing
it and keeping the backslashes as an opaque path). The mangled address
breaks schema-store lookups, and relative $refs resolve to bogus
addresses like "c:///item.schema.json", which NodeIO then tries to
fetch as HTTP URLs.

The fix converts Windows absolute paths (drive-letter and UNC forms) to
"file:" URIs before urijs ever sees them — in normalizeURI, Ref.root,
and Ref.parse — and teaches NodeIO's readableFromFileOrURL to read
"file:" URIs from disk. On POSIX, a drive-letter file URI is read as a
path relative to the working directory, which is what allows the new
regression check (test/check-windows-schema-paths.ts, run by
test/test.ts before the fixtures) to exercise the whole pipeline on
Linux CI, including relative $ref resolution between schema files.

Fixes #2869

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@schani schani left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably first convert our more regular tests to vitest, then we can add these unit tests.

// working directory), which is how the tests exercise this, and Node's fs
// accepts forward slashes on Windows anyway. The addresses were URI-decoded
// when they were normalized, so there's no percent-decoding to do here.
function filePathFromFileURI(fileURI: string): string {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put that in a utility file and add comprehensive unit tests.

// and treats the backslashes as an opaque path), so relative refs resolve to
// bogus addresses (issue #2869). Convert drive-letter and UNC paths to
// "file:" URIs, which NodeIO knows how to read.
function fixWindowsPath(pathOrURI: string): string {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put that in a shared utility file and add comprehensive unit tests.

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.

[BUG]: in Windows it doesn't work with absolute paths and interprets them as a link

1 participant