{"record":{"id":"5d44a65d58f44697","repo":"microsoft/typescript-go","slug":"w-source-file-not-found-v","errorCode":null,"errorMessage":"%w: source file not found: %v","messagePattern":"%w: source file not found: (.+?)","errorType":"validation","errorClass":"ErrClientError","httpStatus":null,"severity":"error","filePath":"internal/api/session.go","lineNumber":530,"sourceCode":"\nfunc (setup checkerSetup) resolveSymbolHandle(id SymbolID) (*ast.Symbol, error) {\n\treturn setup.sd.resolveSymbolHandle(id)\n}\n\nfunc (setup checkerSetup) resolveSignatureHandle(id SignatureID) (*checker.Signature, error) {\n\treturn setup.sd.resolveSignatureHandle(setup.projectID, id)\n}\n\n// resolveLocation resolves an optional location, given either as a node handle or as a\n// file and position. Returns nil when neither is provided.\nfunc (setup checkerSetup) resolveLocation(handle NodeHandle, file *DocumentIdentifier, position *uint32) (*ast.Node, error) {\n\tif handle != \"\" {\n\t\treturn setup.sd.resolveNodeHandle(setup.program, handle)\n\t}\n\tif file != nil && position != nil {\n\t\tsourceFile := setup.program.GetSourceFile(file.ToFileName())\n\t\tif sourceFile == nil {\n\t\t\treturn nil, fmt.Errorf(\"%w: source file not found: %v\", ErrClientError, *file)\n\t\t}\n\t\treturn astnav.GetTouchingPropertyName(sourceFile, sourceFile.GetPositionMap().UTF16ToUTF8(int(*position))), nil\n\t}\n\treturn nil, nil\n}\n\n// setupChecker resolves snapshot, program, and type checker for a project.\n// Callers must defer setup.done() to release the checker.\nfunc (s *Session) setupChecker(ctx context.Context, snapshot SnapshotID, projectHandle ProjectID) (checkerSetup, error) {\n\tsd, err := s.getSnapshotData(snapshot)\n\tif err != nil {\n\t\treturn checkerSetup{}, err\n\t}\n\n\tprogram, err := sd.getProgram(projectHandle)\n\tif err != nil {\n\t\treturn checkerSetup{}, err\n\t}","sourceCodeStart":512,"sourceCodeEnd":548,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/api/session.go#L512-L548","documentation":"resolveLocation was given a file+position (no node handle) and program.GetSourceFile(name) returned nil: \"source file not found: <file>\". The lookup uses DocumentIdentifier.ToFileName(), which returns the URI's file name when a {uri} object was sent, or the FileName string verbatim otherwise - a plain string is NOT normalized to an absolute path. Programs key source files by absolute normalized paths, so any relative/cased-differently/foreign path misses, as does a file that simply is not part of this project's program in this snapshot.","triggerScenarios":"getTypeAtLocation/getSymbolAtPosition/getSymbolsInScope with file: \"src/index.ts\" (relative) instead of the absolute path; passing a URI-shaped string where a plain absolute path was expected (or vice versa); querying a file that was never opened via updateSnapshot or not included by the project's tsconfig; using a file name from a different project's program; case mismatch on case-sensitive filesystems.","commonSituations":"Clients deriving file names from their own relative paths instead of server-returned names; forgetting to open a newly created file before querying it; monorepo files claimed by a different project than the handle passed; editor URIs (file:///...) round-tripped inconsistently between string and {uri} forms.","solutions":["Send the file exactly as the server reports it: call getSourceFileNames and reuse one of those names (or send {uri: ...} consistently)","If sending a plain string, make it absolute and normalized against the server's Cwd","Open the file first via updateSnapshot (openFiles) so the program actually contains it","Verify you are querying the project that owns the file (getDefaultProjectForFile)"],"exampleFix":"// before\nawait call(\"getTypeAtLocation\", { snapshot, project, file: \"src/index.ts\", position }); // relative -> not found\n\n// after\nawait call(\"getTypeAtLocation\", { snapshot, project, file: path.resolve(cwd, \"src/index.ts\"), position });\n// or: file: { uri: \"file:///abs/path/src/index.ts\" }","handlingStrategy":"validation","validationCode":"// TS client: validate the file against the program's known names before querying.\nconst names: string[] = await call(\"getSourceFileNames\", { snapshot, project });\nconst known = new Set(names);\nconst fileToUse = known.has(file) || known.has(file.replace(/\\\\/g, \"/\"));\nif (!fileToUse) {\n  throw new Error(`${file} is not in the program; open it via updateSnapshot or pass an absolute path/{uri}`);\n}\nawait call(\"getTypeAtLocation\", { snapshot, project, file, position });","typeGuard":"const isProgramFile = (f: string, programFiles: Set<string>): boolean =>\n  programFiles.has(f) || programFiles.has(f.replace(/\\\\/g, \"/\"));","tryCatchPattern":"try {\n  return await call(method, params);\n} catch (e) {\n  if (String(e).includes(\"source file not found\")) {\n    // normalize and retry once: absolute path or {uri} form\n    const abs = path.isAbsolute(params.file) ? params.file : path.resolve(cwd, params.file);\n    return await call(method, { ...params, file: { uri: `file://${abs}` } });\n  }\n  throw e;\n}","preventionTips":["Reuse file names verbatim from getSourceFileNames responses","Send plain strings as absolute normalized paths, or consistently use the {uri} form","Open files via updateSnapshot before first query on a new/renamed file","Query the project that owns the file (getDefaultProjectForFile)"],"tags":["source-file","path","program","validation","uri","client-error"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}