{"record":{"id":"2c5a92d7796a0f30","repo":"vxcontrol/pentagi","slug":"failed-to-update-tool-call-log-failed-result-w","errorCode":null,"errorMessage":"failed to update tool call log failed result: %w","messagePattern":"failed to update tool call log failed result: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/controller/tclog.go","lineNumber":108,"sourceCode":"\n\tw.pub.ToolCallLogUpdated(ctx, tc)\n\n\treturn nil\n}\n\nfunc (w *flowToolCallLogWorker) UpdateLogFailed(\n\tctx context.Context,\n\tid int64,\n\tresult string,\n\tdurationSeconds float64,\n) error {\n\ttc, err := w.db.UpdateToolcallFailedResult(ctx, database.UpdateToolcallFailedResultParams{\n\t\tResult:          result,\n\t\tDurationSeconds: durationSeconds,\n\t\tID:              id,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to update tool call log failed result: %w\", err)\n\t}\n\n\tw.pub.ToolCallLogUpdated(ctx, tc)\n\n\treturn nil\n}\n\nfunc (w *flowToolCallLogWorker) GetLog(ctx context.Context, id int64) (database.Toolcall, error) {\n\ttc, err := w.db.GetFlowToolcall(ctx, database.GetFlowToolcallParams{\n\t\tID:     id,\n\t\tFlowID: w.flowID,\n\t})\n\tif err != nil {\n\t\treturn database.Toolcall{}, fmt.Errorf(\"failed to get tool call log: %w\", err)\n\t}\n\n\treturn tc, nil\n}","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/controller/tclog.go#L90-L126","documentation":"UpdateLogFailed marks a tool call as failed via db.UpdateToolcallFailedResult. Same wrapping pattern as the success path: the thrown error is the raw database error wrapped with context, usually sql.ErrNoRows for an unknown/stale toolcall ID or a transient connection failure.","triggerScenarios":"Recording failure for an ID that was never created (e.g. PutLog failed earlier and its error was swallowed), an ID from another flow, or a canceled context / broken connection during the UPDATE.","commonSituations":"Agent error-handling paths that report failure after a timeout while the DB write already failed upstream; rows cleaned by retention jobs before the failure result arrives.","solutions":["Check errors.Is(err, sql.ErrNoRows) to detect a stale/unknown toolcall ID","Make sure PutLog errors abort the tool execution path so UpdateLogFailed is never called with an invalid ID","Verify the toolcall row still exists (SELECT via GetLog) before updating","Inspect the wrapped error and DB logs for connection/constraint causes","Treat as non-fatal and log if the row was already finished by a concurrent path"],"exampleFix":"// before\nerr := worker.UpdateLogFailed(ctx, id, errMsg, dur)\nif err != nil { panic(err) }\n// after\nerr := worker.UpdateLogFailed(ctx, id, errMsg, dur)\nif errors.Is(err, sql.ErrNoRows) {\n    log.Warn().Int64(\"id\", id).Msg(\"toolcall missing; cannot record failure\")\n} else if err != nil {\n    return err\n}","handlingStrategy":"try-catch","validationCode":"func canRecordFailure(ctx context.Context, q database.Querier, flowID, id int64) error {\n    _, err := q.GetFlowToolcall(ctx, database.GetFlowToolcallParams{ID: id, FlowID: flowID})\n    return err // nil means the row exists and failure can be recorded\n}","typeGuard":"func isNoRows(err error) bool { return errors.Is(err, sql.ErrNoRows) }","tryCatchPattern":"err := worker.UpdateLogFailed(ctx, id, errMsg, dur)\nif isNoRows(err) {\n    log.Warn().Int64(\"id\", id).Msg(\"cannot record failure: toolcall row gone\")\n    return nil\n}\nif err != nil {\n    return fmt.Errorf(\"record failure: %w\", err)\n}","preventionTips":["Abort the tool path immediately when PutLog fails so UpdateLogFailed never runs with a bad ID","Make failure recording idempotent — repeated failures for one call should not error","Check the retention/cleanup schedule against maximum tool durations","Distinguish sql.ErrNoRows from transient DB errors before alerting","Include the wrapped cause in logs (use %v on errors.Unwrap) for triage"],"tags":["database","postgresql","no-rows"],"backgroundTag":"sql-no-rows","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}