vxcontrol/pentagi · error
failed to update tool call log failed result: %w
Error message
failed to update tool call log failed result: %w
What it means
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.
Source
Thrown at backend/pkg/controller/tclog.go:108
w.pub.ToolCallLogUpdated(ctx, tc)
return nil
}
func (w *flowToolCallLogWorker) UpdateLogFailed(
ctx context.Context,
id int64,
result string,
durationSeconds float64,
) error {
tc, err := w.db.UpdateToolcallFailedResult(ctx, database.UpdateToolcallFailedResultParams{
Result: result,
DurationSeconds: durationSeconds,
ID: id,
})
if err != nil {
return fmt.Errorf("failed to update tool call log failed result: %w", err)
}
w.pub.ToolCallLogUpdated(ctx, tc)
return nil
}
func (w *flowToolCallLogWorker) GetLog(ctx context.Context, id int64) (database.Toolcall, error) {
tc, err := w.db.GetFlowToolcall(ctx, database.GetFlowToolcallParams{
ID: id,
FlowID: w.flowID,
})
if err != nil {
return database.Toolcall{}, fmt.Errorf("failed to get tool call log: %w", err)
}
return tc, nil
}View on GitHub (pinned to ea665308ba)
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
Example fix
// before
err := worker.UpdateLogFailed(ctx, id, errMsg, dur)
if err != nil { panic(err) }
// after
err := worker.UpdateLogFailed(ctx, id, errMsg, dur)
if errors.Is(err, sql.ErrNoRows) {
log.Warn().Int64("id", id).Msg("toolcall missing; cannot record failure")
} else if err != nil {
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
func canRecordFailure(ctx context.Context, q database.Querier, flowID, id int64) error {
_, err := q.GetFlowToolcall(ctx, database.GetFlowToolcallParams{ID: id, FlowID: flowID})
return err // nil means the row exists and failure can be recorded
} Type guard
func isNoRows(err error) bool { return errors.Is(err, sql.ErrNoRows) } Try / catch
err := worker.UpdateLogFailed(ctx, id, errMsg, dur)
if isNoRows(err) {
log.Warn().Int64("id", id).Msg("cannot record failure: toolcall row gone")
return nil
}
if err != nil {
return fmt.Errorf("record failure: %w", err)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- failed to update tool call log result: %w
- failed to create tool call log: %w
- failed to create termlog: %w
- failed to get containers: %w
- knowledge: list user docs: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/2c5a92d7796a0f30.
Report an issue: GitHub.