vxcontrol/pentagi · error
failed to update tool call log result: %w
Error message
failed to update tool call log result: %w
What it means
UpdateLogSuccess marks a tool call as finished by calling db.UpdateToolcallFinishedResult. This error wraps the underlying SQL failure — most commonly sql.ErrNoRows because the toolcall ID does not exist (or belongs to another flow / was already finished, depending on the query), or a transient DB error.
Source
Thrown at backend/pkg/controller/tclog.go:88
w.pub.ToolCallLogAdded(ctx, tc)
return tc.ID, nil
}
func (w *flowToolCallLogWorker) UpdateLogSuccess(
ctx context.Context,
id int64,
result string,
durationSeconds float64,
) error {
tc, err := w.db.UpdateToolcallFinishedResult(ctx, database.UpdateToolcallFinishedResultParams{
Result: result,
DurationSeconds: durationSeconds,
ID: id,
})
if err != nil {
return fmt.Errorf("failed to update tool call log result: %w", err)
}
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,
})View on GitHub (pinned to ea665308ba)
Solutions
- Check errors.Is(err, sql.ErrNoRows) — if so the ID is wrong or the row was deleted
- Log and return the ID from PutLog rather than reconstructing or caching it
- Guard against double-update with a status check / idempotency in the calling agent code
- Inspect the wrapped error for constraint or connection details in the DB logs
- Retry only transient driver errors; missing rows will never succeed on retry
Example fix
// before
if err := worker.UpdateLogSuccess(ctx, id, result, dur); err != nil {
return fmt.Errorf("mark success: %w", err)
}
// after
if err := worker.UpdateLogSuccess(ctx, id, result, dur); err != nil {
if errors.Is(err, sql.ErrNoRows) {
log.Warn().Int64("toolcall_id", id).Msg("toolcall already gone, skipping success update")
return nil
}
return fmt.Errorf("mark success: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
func toolcallExists(ctx context.Context, q database.Querier, id int64) bool {
_, err := q.GetFlowToolcall(ctx, database.GetFlowToolcallParams{ID: id, FlowID: currentFlowID})
return err == nil
} Type guard
func isNoRows(err error) bool { return errors.Is(err, sql.ErrNoRows) } Try / catch
err := worker.UpdateLogSuccess(ctx, id, result, dur)
switch {
case err == nil:
// ok
case isNoRows(err):
log.Warn().Int64("id", id).Msg("toolcall missing; skipping success update")
case errors.Is(err, context.Canceled):
// treat as non-fatal, result already delivered to agent
log.Warn().Err(err).Msg("success update canceled")
default:
return fmt.Errorf("update success: %w", err)
} Prevention
- Complete each toolcall exactly once — use a state machine around PutLog/Update*
- Never cache toolcall IDs across flow restarts
- Log the returned tc.ID from PutLog immediately and pass it explicitly
- Treat sql.ErrNoRows as idempotent-success in idempotent update paths
- Watch DB failover logs during long tool executions
When it happens
Trigger: Calling UpdateLogSuccess with an id that was never inserted, an id from a different flow worker, a duplicate completion after the row was already transitioned out of running status, or DB connection loss/canceled context during the UPDATE.
Common situations: Double completion when both success and failure paths fire for one call; using an ID cached from a previous flow run; DB failover mid-execution of long-running tools.
Related errors
- failed to update tool call log failed 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/336ad85e114fcdda.
Report an issue: GitHub.