vxcontrol/pentagi · error
failed to parse stop_flow args: %w
Error message
failed to parse stop_flow args: %w
What it means
The stop_flow tool could not unmarshal its raw JSON arguments into StopFlowAction. The decode error is wrapped so the original json error remains inspectable. It guards the boundary between the agent tool-call protocol and the typed action struct.
Source
Thrown at backend/pkg/tools/flow_manager.go:620
"Call %s with detail='summary' to see the final status and results.",
GetFlowStatusToolName), nil
}
// stopFlowTool implements stop_flow.
type stopFlowTool struct {
flowID int64
db database.Querier
handler func(ctx context.Context, reason string) error
}
func NewStopFlowTool(flowID int64, db database.Querier, handler func(ctx context.Context, reason string) error) *stopFlowTool {
return &stopFlowTool{flowID: flowID, db: db, handler: handler}
}
func (t *stopFlowTool) Handle(ctx context.Context, name string, args json.RawMessage) (string, error) {
var action StopFlowAction
if err := json.Unmarshal(args, &action); err != nil {
return "", fmt.Errorf("failed to parse stop_flow args: %w", err)
}
tasks, err := t.db.GetFlowTasks(ctx, t.flowID)
if err != nil {
return "", fmt.Errorf("failed to check flow status: %w", err)
}
isRunning := false
for _, task := range tasks {
if task.Status == database.TaskStatusRunning {
isRunning = true
break
}
}
if !isRunning {
return "No running task found — the flow is already in 'waiting' state and ready to accept input.", nil
}View on GitHub (pinned to ea665308ba)
Solutions
- Send stop_flow args as a valid JSON object with correct types, e.g. {"reason": "user requested stop"}.
- Check the wrapped inner error to distinguish SyntaxError (bad JSON) from UnmarshalTypeError (bad field type).
- Avoid double-encoding: pass an object, not a JSON string of an object.
- Retry the tool call if the args were generated by an LLM — regenerated JSON is often valid.
Example fix
// before (double-encoded)
args := `"{\"reason\":\"done\"}"`
// after
args := `{"reason":"done"}` Defensive patterns
Strategy: validation
Validate before calling
const args = { reason: 'user requested stop' };
if (typeof args.reason !== 'string') throw new TypeError('reason must be a string');
JSON.parse(JSON.stringify(args)); // round-trip validate Type guard
function isStopFlowAction(v: unknown): v is { reason?: string } {
return typeof v === 'object' && v !== null &&
(!('reason' in v) || typeof (v as any).reason === 'string');
} Try / catch
try {
await tool.call('stop_flow', args);
} catch (err) {
if (String(err).includes('failed to parse stop_flow args')) {
// rebuild args as a valid JSON object and retry
}
} Prevention
- Pass reason as a string, never a number
- Do not double-encode JSON strings as args
- Validate against the tool's JSON schema before calling
- Escape special characters in the reason text
When it happens
Trigger: Calling stop_flow with malformed JSON, a non-object payload, or wrong-typed fields — e.g. {"reason": 123} (number instead of string) or truncated JSON produced by the LLM or client.
Common situations: LLM emits invalid JSON for the tool call; a caller stringifies args incorrectly (double-encoded JSON like "{\"reason\":\"x\"}"); reason field given a non-string value.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse %s args: %w
- input must not be empty
- failed to parse patch_flow_subtasks args: %w
- unknown search_type: %s
- Internal
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/7e04cfb8daa6bc2a.
Report an issue: GitHub.