{"record":{"id":"812c1de5cda0d0dc","repo":"microsoft/typescript-go","slug":"w-type-handle-d-not-found-no-registry-for-proj","errorCode":null,"errorMessage":"%w: type handle %d not found (no registry for project %s)","messagePattern":"%w: type handle (.+?) not found \\(no registry for project (.+?)\\)","errorType":"validation","errorClass":"ErrClientError","httpStatus":null,"severity":"error","filePath":"internal/api/session.go","lineNumber":266,"sourceCode":"\n\treturn symbol, nil\n}\n\n// resolveTypeHandle resolves a type handle within the project's registry.\nfunc (sd *snapshotData) resolveTypeHandle(projectID ProjectID, handle TypeID) (*checker.Type, error) {\n\tif handle == 0 {\n\t\treturn nil, fmt.Errorf(\"%w: empty type handle\", ErrClientError)\n\t}\n\tif projectID == \"\" {\n\t\treturn nil, fmt.Errorf(\"%w: empty project ID for type handle %d\", ErrClientError, handle)\n\t}\n\n\tsd.projectRegistriesMu.RLock()\n\treg := sd.projectRegistries[projectID]\n\tsd.projectRegistriesMu.RUnlock()\n\n\tif reg == nil {\n\t\treturn nil, fmt.Errorf(\"%w: type handle %d not found (no registry for project %s)\", ErrClientError, handle, projectID)\n\t}\n\n\treg.typeRegistryMu.RLock()\n\tt, ok := reg.typeRegistry[handle]\n\treg.typeRegistryMu.RUnlock()\n\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"%w: type handle %d not found in project registry\", ErrClientError, handle)\n\t}\n\n\treturn t, nil\n}\n\n// resolveSignatureHandle resolves a signature handle within the project's registry.\nfunc (sd *snapshotData) resolveSignatureHandle(projectID ProjectID, handle SignatureID) (*checker.Signature, error) {\n\tif handle == 0 {\n\t\treturn nil, fmt.Errorf(\"%w: empty signature handle\", ErrClientError)\n\t}","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/api/session.go#L248-L284","documentation":"resolveTypeHandle found no projectRegistryData for the given ProjectID, reported as \"type handle N not found (no registry for project P)\". A project's type registry is created lazily the first time a type response is registered in that project within this snapshot, so 'no registry' means no type-returning call has ever produced types for this project here - in practice the ProjectID is wrong or stale for this snapshot.","triggerScenarios":"Sending a type handle with a project handle from a different snapshot (registries are snapshot-scoped); mixing handles: type id from project A paired with project B's handle; a project that legitimately has no registered types yet being queried with a fabricated type id.","commonSituations":"Client caches {project, type} pairs across updateSnapshot cycles; monorepo clients routing queries between sibling projects and swapping ids; session restart wiping registries while the client kept its handle table.","solutions":["Re-fetch the type in the current snapshot before querying its sub-properties","Keep project, snapshot, and type id together as one unit; invalidate the whole unit on snapshot change","Verify the project handle itself still resolves (a wrong project path also produces this error)"],"exampleFix":"// before\nawait call(\"getTypesOfType\", { snapshot, project: oldProject, type: cachedTypeId }); // no registry\n\n// after\nconst sym = await call(\"getSymbolAtPosition\", { snapshot, project, file, position });\nconst t = sym && await call(\"getTypeOfSymbol\", { snapshot, project, symbol: sym.id });\nif (t) await call(\"getTypesOfType\", { snapshot, project, type: t.id });","handlingStrategy":"validation","validationCode":"// TS client: validate scope before the request.\nconst key = `${snapshot}:${project}`;\nif (!typeRegistriesSeen.has(key)) {\n  // no type-producing call has run for this project in this snapshot;\n  // a type handle claimed to come from there is stale or mismatched\n  throw new Error(`no type registry for ${key}; re-acquire the type via getTypeOfSymbol/getTypeAtPosition`);\n}","typeGuard":"const isScopedTypeHandle = (h: { snapshot: bigint; project: string; id: number }, cur: bigint): boolean =>\n  h.snapshot === cur && h.project.length > 0 && h.id > 0;","tryCatchPattern":null,"preventionTips":["Invalidate {project, type} caches on every snapshot change","Never recombine a type id with a different project's handle","After any error mentioning 'no registry', re-fetch via getTypeOfSymbol/getTypeAtPosition in the current snapshot"],"tags":["type-handle","registry","project","snapshot","stale-handle","client-error"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}