microsoft/typescript-go · error
DocumentIdentifier: expected string or object, got %v
Error message
DocumentIdentifier: expected string or object, got %v
What it means
DocumentIdentifier.UnmarshalJSONFrom accepts only a JSON string (a file name) or an object with a uri field; any other token kind - number, boolean, null, array - is rejected with the token kind printed. This type appears in file-change notifications and most file-addressed request params.
Source
Thrown at internal/api/proto.go:279
if err != nil {
return err
}
isURI := key.String() == "uri"
val, err := dec.ReadToken()
if err != nil {
return err
}
if isURI {
d.URI = lsproto.DocumentUri(val.String())
}
}
// Consume the closing brace
if _, err := dec.ReadToken(); err != nil {
return err
}
return nil
default:
return fmt.Errorf("DocumentIdentifier: expected string or object, got %v", tok.Kind())
}
}
func (d DocumentIdentifier) ToFileName() string {
if d.URI != "" {
return d.URI.FileName()
}
return d.FileName
}
// ToURI returns the document URI for this identifier. An explicitly provided URI
// is returned as-is; a file name is first normalized to an absolute path against
// cwd before being converted to a URI.
func (d DocumentIdentifier) ToURI(cwd string) lsproto.DocumentUri {
if d.URI != "" {
return d.URI
}
return lsconv.FileNameToDocumentURI(tspath.GetNormalizedAbsolutePath(d.FileName, cwd))View on GitHub (pinned to 1bcfa18d79)
Solutions
- Send either "/abs/path/file.ts" or {"uri":"file:///abs/path/file.ts"}
- Type the field as string | { uri: string } on the client and lint against anything else
- Check for accidental null from optional chaining or unset variables before serializing
- Validate outgoing JSON with the type guard below during development
Example fix
// before
{ "file": null }
// after
{ "file": "/abs/path/file.ts" }
// or
{ "file": { "uri": "file:///abs/path/file.ts" } } Defensive patterns
Strategy: type-guard
Validate before calling
// Go side, before marshalling outgoing params:
func validDocument(d any) bool {
switch v := d.(type) {
case string:
return v != ""
case map[string]any:
_, ok := v["uri"]
return ok
}
return false
} Type guard
// TypeScript client side
function isDocumentIdentifier(v: unknown): v is string | { uri: string } {
return typeof v === "string" ||
(typeof v === "object" && v !== null && typeof (v as { uri?: unknown }).uri === "string");
} Prevention
- Type the field as string | { uri: string } end to end
- Guard optional fields against null before serializing
- Add a client-side lint/test that round-trips every document payload through the guard
When it happens
Trigger: Sending "file": 123, null, true, or an array where the document goes; a numeric or null value slipping through a loosely typed client serializer.
Common situations: TypeScript clients with `file: string | number`-style loose types; optional fields defaulting to null; hand-built JSON request strings.
Related errors
- failed to unmarshal %T: %w
- data too short for header: %d bytes
- ErrInvalidRequest
- %w: %w
- missing required properties: %s
AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16).
Data as JSON: /api/errors/277d7ce661bb12e2.
Report an issue: GitHub.