{"record":{"id":"319b7f4442a8eb76","repo":"vxcontrol/pentagi","slug":"unknown-perform-result-d","errorCode":null,"errorMessage":"unknown perform result: %d","messagePattern":"unknown perform result: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/controller/subtask.go","lineNumber":349,"sourceCode":"\n\tswitch performResult {\n\tcase providers.PerformResultWaiting:\n\t\tif err := stw.SetStatus(ctx, database.SubtaskStatusWaiting); err != nil {\n\t\t\tstw.handleInterrupting(err)\n\t\t\treturn err\n\t\t}\n\tcase providers.PerformResultDone:\n\t\tif err := stw.SetStatus(ctx, database.SubtaskStatusFinished); err != nil {\n\t\t\tstw.handleInterrupting(err)\n\t\t\treturn fmt.Errorf(\"failed to set subtask %d status to finished: %w\", subtaskID, err)\n\t\t}\n\tcase providers.PerformResultError:\n\t\tif err := stw.SetStatus(ctx, database.SubtaskStatusFailed); err != nil {\n\t\t\tstw.handleInterrupting(err)\n\t\t\treturn fmt.Errorf(\"failed to set subtask %d status to failed: %w\", subtaskID, err)\n\t\t}\n\tdefault:\n\t\treturn fmt.Errorf(\"unknown perform result: %d\", performResult)\n\t}\n\n\treturn nil\n}\n\n// handleInterrupting sets this subtask (and task/flow via SetStatus back-propagation)\n// to Waiting when err is context.Canceled or context.DeadlineExceeded. Use after the subtask\n// was advanced past Waiting (e.g. Running) but the run aborts before PerformAgentChain's\n// normal error handler, or when a late SetStatus fails with a context interruption.\nfunc (stw *subtaskWorker) handleInterrupting(err error) {\n\tif err == nil {\n\t\treturn\n\t}\n\tif !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) {\n\t\treturn\n\t}\n\tif stw.IsCompleted() {\n\t\treturn","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/controller/subtask.go#L331-L367","documentation":"Sentinel-style error returned when Provider.PerformAgentChain yields a performResult value outside the known set (Waiting, Done, Error). It indicates the provider adapter returned an undocumented result code — typically a bug in a new or custom provider implementation rather than a runtime condition.","triggerScenarios":"subtaskWorker.Run()'s switch on performResult falls through to default because the provider returned a PerformResult constant the controller doesn't recognize — e.g. a newly added enum value in pkg/providers not yet handled here, or a custom provider returning a zero-value/overflowed code.","commonSituations":"Upgrading PentAGI with a custom provider plugin compiled against a newer providers package; hand-written provider adapters returning an int result not from the PerformResult enum; Go version/package version skew between backend modules.","solutions":["Check the provider implementation used for this subtask — make it return only providers.PerformResultWaiting/Done/Error.","If a new PerformResult enum value was added in pkg/providers, extend the switch in subtaskWorker.Run to handle it.","Rebuild the backend binary so provider package and controller are from the same version (go mod tidy && go build).","Log the raw performResult value to identify which provider/constant leaked through."],"exampleFix":"// before: custom provider returns an unhandled value\nreturn 42, nil\n// after: return only enum values\nreturn providers.PerformResultDone, nil","handlingStrategy":"validation","validationCode":"switch r := performResult; r {\ncase providers.PerformResultWaiting, providers.PerformResultDone, providers.PerformResultError:\n    // ok\ndefault:\n    return fmt.Errorf(\"provider returned invalid perform result %d\", r)\n}","typeGuard":"func validPerformResult(r providers.PerformResult) bool {\n    switch r {\n    case providers.PerformResultWaiting, providers.PerformResultDone, providers.PerformResultError:\n        return true\n    }\n    return false\n}","tryCatchPattern":"if err := stw.Run(ctx); err != nil {\n    if strings.HasPrefix(err.Error(), \"unknown perform result\") {\n        logrus.WithError(err).Error(\"provider contract violation — check provider version\")\n        return err // non-retryable\n    }\n}","preventionTips":["Only return PerformResult enum constants from provider implementations — never raw ints.","Rebuild the whole backend binary after upgrading pkg/providers so enum values are consistent.","Add a unit test asserting every provider returns one of the three known results.","Handle new PerformResult enum values in subtaskWorker.Run immediately when added upstream."],"tags":["provider","enum","subtask","version-skew"],"backgroundTag":"invalid-enum-value","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}