{"record":{"id":"7e04cfb8daa6bc2a","repo":"vxcontrol/pentagi","slug":"failed-to-parse-stop-flow-args-w","errorCode":null,"errorMessage":"failed to parse stop_flow args: %w","messagePattern":"failed to parse stop_flow args: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/flow_manager.go","lineNumber":620,"sourceCode":"\t\t\t\"Call %s with detail='summary' to see the final status and results.\",\n\t\tGetFlowStatusToolName), nil\n}\n\n// stopFlowTool implements stop_flow.\ntype stopFlowTool struct {\n\tflowID  int64\n\tdb      database.Querier\n\thandler func(ctx context.Context, reason string) error\n}\n\nfunc NewStopFlowTool(flowID int64, db database.Querier, handler func(ctx context.Context, reason string) error) *stopFlowTool {\n\treturn &stopFlowTool{flowID: flowID, db: db, handler: handler}\n}\n\nfunc (t *stopFlowTool) Handle(ctx context.Context, name string, args json.RawMessage) (string, error) {\n\tvar action StopFlowAction\n\tif err := json.Unmarshal(args, &action); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to parse stop_flow args: %w\", err)\n\t}\n\n\ttasks, err := t.db.GetFlowTasks(ctx, t.flowID)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to check flow status: %w\", err)\n\t}\n\n\tisRunning := false\n\tfor _, task := range tasks {\n\t\tif task.Status == database.TaskStatusRunning {\n\t\t\tisRunning = true\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif !isRunning {\n\t\treturn \"No running task found — the flow is already in 'waiting' state and ready to accept input.\", nil\n\t}","sourceCodeStart":602,"sourceCodeEnd":638,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/flow_manager.go#L602-L638","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (double-encoded)\nargs := `\"{\\\"reason\\\":\\\"done\\\"}\"`\n// after\nargs := `{\"reason\":\"done\"}`","handlingStrategy":"validation","validationCode":"const args = { reason: 'user requested stop' };\nif (typeof args.reason !== 'string') throw new TypeError('reason must be a string');\nJSON.parse(JSON.stringify(args)); // round-trip validate","typeGuard":"function isStopFlowAction(v: unknown): v is { reason?: string } {\n  return typeof v === 'object' && v !== null &&\n    (!('reason' in v) || typeof (v as any).reason === 'string');\n}","tryCatchPattern":"try {\n  await tool.call('stop_flow', args);\n} catch (err) {\n  if (String(err).includes('failed to parse stop_flow args')) {\n    // rebuild args as a valid JSON object and retry\n  }\n}","preventionTips":["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"],"tags":["json","args-parsing","tool-call","validation"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}