{"record":{"id":"b015aef802e49fb1","repo":"microsoft/typescript-go","slug":"project-not-found-for-update-s","errorCode":null,"errorMessage":"project not found for update: %s","messagePattern":"project not found for update: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/project/projectcollectionbuilder.go","lineNumber":212,"sourceCode":"\tif apiRequest.OpenFiles != nil {\n\t\tfor uri := range apiRequest.OpenFiles.Keys() {\n\t\t\tfileName := uri.FileName()\n\t\t\tpath := b.toPath(fileName)\n\t\t\tif b.apiState.openFiles == nil {\n\t\t\t\tb.apiState.openFiles = make(map[tspath.Path]apiOpenedFile)\n\t\t\t}\n\t\t\tentry := b.apiState.openFiles[path]\n\t\t\tentry.fileName = fileName\n\t\t\tentry.refCount++\n\t\t\tb.apiState.openFiles[path] = entry\n\t\t}\n\t}\n\n\tfor configPath := range b.apiState.openProjects {\n\t\tif entry, ok := b.configuredProjects.Load(configPath); ok {\n\t\t\tb.updateProgram(entry, logger)\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"project not found for update: %s\", configPath)\n\t\t}\n\t}\n\n\tfor _, overlay := range b.fs.overlays {\n\t\tif entry := b.findDefaultConfiguredProject(overlay.FileName(), b.toPath(overlay.FileName())); entry != nil {\n\t\t\tdelete(projectsToClose, entry.Value().configFilePath)\n\t\t}\n\t}\n\n\tfor projectPath := range projectsToClose {\n\t\tif entry, ok := b.configuredProjects.Load(projectPath); ok {\n\t\t\tb.deleteConfiguredProject(entry, logger)\n\t\t}\n\t}\n\n\t// Ensure each API-opened file is placed like LSP's textDocument/didOpen: search\n\t// up ancestor directories for a configured project that contains it, and only\n\t// fall back to the inferred project if none is found. This also keeps already","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/project/projectcollectionbuilder.go#L194-L230","documentation":"Raised during the update phase of project collection building: the builder iterates apiState.openProjects (accumulated from earlier open requests) and must run updateProgram on each — but a config path is present in open-projects state while b.configuredProjects no longer has an entry for it. That means the project was closed/evicted from the registry while the API still counts it as open, an internal state divergence the builder refuses to paper over.","triggerScenarios":"Project closed (config file deleted, or a close-projects request) between the open call and the next update; failed loads evicting the configured project while refcounts in apiState remain; interleaved open/close/update API requests hitting a race; config file invalidated by watch events mid-sequence.","commonSituations":"Rapid open→update sequences from automation while file watchers concurrently remove projects; tsconfig deleted between requests; concurrent API clients one closing and one updating the same project.","solutions":["Re-open the project (it will be re-created via findOrCreateProject) before issuing the next update","Serialize open/close/update requests per config path instead of racing them","If the project was intentionally closed, also remove it from your open-projects tracking so updates skip it"],"exampleFix":"// before\napi.Update(ctx, req) // openProjects still lists a closed project\n\n// after\nif !api.IsProjectOpen(configPath) {\n\tapi.Open(ctx, configPath) // re-materialize before update\n}\napi.Update(ctx, req)","handlingStrategy":"validation","validationCode":"// verify the project is still open before issuing updates\nfor cfg := range myOpenProjects {\n\tif !apiSession.ProjectExists(cfg) {\n\t\tif err := apiSession.Open(cfg); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n}\napiSession.Update(ctx)","typeGuard":null,"tryCatchPattern":"err := builder.Build(apiRequest)\nif err != nil && strings.Contains(err.Error(), \"project not found for update\") {\n\tcfgPath := extractPath(err) // parse %s from the message\n\tapiSession.Open(cfgPath)   // re-materialize, then retry once\n\treturn builder.Build(apiRequest)\n}","preventionTips":["Serialize open/close/update calls per config path; avoid racing watchers","After closing a project, stop updating it and clear it from your open set","Treat a config-file deletion as a signal to drop dependent update traffic"],"tags":["project","state","lifecycle","race"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}