{"record":{"id":"964571bd41dd42fe","repo":"vxcontrol/pentagi","slug":"assistant-d-not-found","errorCode":null,"errorMessage":"assistant %d not found","messagePattern":"assistant (.+?) not found","errorType":"exception","errorClass":null,"httpStatus":404,"severity":"error","filePath":"backend/pkg/controller/flow.go","lineNumber":598,"sourceCode":"\t\tif err := taw.Finish(ctx); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to finish assistant %d: %w\", aw.GetAssistantID(), err)\n\t\t}\n\t}\n\n\tfw.aws[aw.GetAssistantID()] = aw\n\n\treturn nil\n}\n\nfunc (fw *flowWorker) GetAssistant(ctx context.Context, assistantID int64) (AssistantWorker, error) {\n\tfw.awsMX.Lock()\n\tdefer fw.awsMX.Unlock()\n\n\tif aw, ok := fw.aws[assistantID]; ok {\n\t\treturn aw, nil\n\t}\n\n\treturn nil, fmt.Errorf(\"assistant %d not found\", assistantID)\n}\n\nfunc (fw *flowWorker) DeleteAssistant(ctx context.Context, assistantID int64) error {\n\tfw.awsMX.Lock()\n\tdefer fw.awsMX.Unlock()\n\n\taw, ok := fw.aws[assistantID]\n\tif ok {\n\t\tif err := aw.Finish(ctx); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to finish assistant %d: %w\", assistantID, err)\n\t\t}\n\n\t\tdelete(fw.aws, assistantID)\n\t}\n\n\tif assistant, err := fw.flowCtx.DB.DeleteAssistant(ctx, assistantID); err != nil {\n\t\treturn fmt.Errorf(\"failed to delete assistant %d: %w\", assistantID, err)\n\t} else {","sourceCodeStart":580,"sourceCodeEnd":616,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/controller/flow.go#L580-L616","documentation":"flowWorker.GetAssistant looks up a registered AssistantWorker by ID under the aws mutex; if the map has no entry it returns 'assistant %d not found'. The registry holds only assistants spawned and still alive on this flow worker — deleted or never-started assistants are absent.","triggerScenarios":"Calling GetAssistant with an ID for an assistant that was never added on this flow, was removed via DeleteAssistant, was registered on a different flow's worker, or with a stale ID after flow reload (in-memory map repopulated only for active assistants).","commonSituations":"Client sends an assistant ID from a previous session after server restart; cross-flow ID reuse; DeleteAssistant already removed the worker but the caller caches the ID; race where the caller queries before AddAssistant completes.","solutions":["Call ListAssistants first and match the ID against live workers before fetching.","Re-create/register the assistant via AddAssistant if it should exist but was dropped (e.g. after reload).","Confirm the assistant belongs to the same flow — IDs are only valid within one flowWorker.","Treat as not-found (404) in API layers and refresh the client's assistant list.","Serialize create-then-get sequences to avoid the registration race."],"exampleFix":"// before\naw, err := fw.GetAssistant(ctx, assistantID) // fails after reload: worker not in map\n// after\nfor _, live := range fw.ListAssistants(ctx) {\n    if live.GetAssistantID() == assistantID {\n        return use(live)\n    }\n}\nreturn fmt.Errorf(\"assistant %d is not active on this flow\", assistantID)","handlingStrategy":"validation","validationCode":"live := fw.ListAssistants(ctx)\nfound := false\nfor _, a := range live {\n    if a.GetAssistantID() == assistantID { found = true; break }\n}\nif !found { return ErrAssistantNotActive }","typeGuard":"func assistantActive(fw FlowWorker, ctx context.Context, id int64) bool {\n    for _, a := range fw.ListAssistants(ctx) {\n        if a.GetAssistantID() == id { return true }\n    }\n    return false\n}","tryCatchPattern":"aw, err := fw.GetAssistant(ctx, assistantID)\nif err != nil {\n    if strings.Contains(err.Error(), \"not found\") { return http.StatusNotFound }\n    return http.StatusInternalServerError\n}","preventionTips":["Refresh assistant IDs after server restarts — in-memory workers don't survive reloads","Never reuse assistant IDs across flows","Complete AddAssistant before querying GetAssistant (avoid the registration race)","Drop cached assistant references after DeleteAssistant succeeds"],"tags":["go","not-found","assistant","registry"],"backgroundTag":"entity-not-found","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}