{"record":{"id":"0442227f5019079b","repo":"vxcontrol/pentagi","slug":"failed-to-parse-s-args-w","errorCode":null,"errorMessage":"failed to parse %s args: %w","messagePattern":"failed to parse (.+?) args: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/flow_manager.go","lineNumber":545,"sourceCode":"// currently running task finishes or the caller-supplied timeout expires.\ntype waitFlowCompletionTool struct {\n\tflowID  int64\n\tdb      database.Querier\n\thandler func(ctx context.Context) error\n}\n\nfunc NewWaitFlowCompletionTool(\n\tflowID int64,\n\tdb database.Querier,\n\thandler func(ctx context.Context) error,\n) *waitFlowCompletionTool {\n\treturn &waitFlowCompletionTool{flowID: flowID, db: db, handler: handler}\n}\n\nfunc (t *waitFlowCompletionTool) Handle(ctx context.Context, name string, args json.RawMessage) (string, error) {\n\tvar action WaitFlowCompletionAction\n\tif err := json.Unmarshal(args, &action); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to parse %s args: %w\", WaitFlowCompletionToolName, err)\n\t}\n\n\ttimeout := time.Duration(action.Timeout.Int64()) * time.Second\n\tswitch {\n\tcase timeout <= 0:\n\t\ttimeout = waitFlowDefaultTimeout\n\tcase timeout > waitFlowMaxTimeout:\n\t\ttimeout = waitFlowMaxTimeout\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\tif len(tasks) == 0 {\n\t\treturn fmt.Sprintf(\n\t\t\t\"The automation has not been created yet — no tasks exist. \"+","sourceCodeStart":527,"sourceCodeEnd":563,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/flow_manager.go#L527-L563","documentation":"The wait_flow_completion tool failed to JSON-unmarshal the raw arguments it received into WaitFlowCompletionAction. The underlying decode error is wrapped with %w, so errors.Is/As still work against the original json.UnmarshalTypeError or SyntaxError. This is a defensive check at the boundary of the agent tool-call protocol: the LLM produced arguments that are not valid JSON or do not match the action struct.","triggerScenarios":"Calling wait_flow_completion with args that are malformed JSON (truncated string, unquoted keys, trailing commas), a non-object payload (e.g. a bare string or array), or a wrong-typed field (e.g. timeout: \"30\" as a string instead of a number, or nested unknown structure causing UnmarshalTypeError).","commonSituations":"An LLM generates slightly invalid JSON when constructing tool calls; a client SDK serializes the args object as a string instead of an object; prompt templating mangles the JSON; long outputs truncate mid-JSON when the caller builds args manually.","solutions":["Inspect the wrapped inner error to see if it is a SyntaxError (malformed JSON) or UnmarshalTypeError (wrong field type) and fix the args accordingly.","Ensure the caller passes a valid JSON object with correct field types, e.g. {\"timeout\": 30} with timeout as a number.","Validate/generate args through a typed struct or JSON-schema-aware client instead of hand-built strings.","Re-send the tool call; LLM-generated JSON errors are often transient generation mistakes."],"exampleFix":"// before (invalid: timeout as string)\nargs := `{\"timeout\": \"30\"}`\n// after\nargs := `{\"timeout\": 30}`","handlingStrategy":"validation","validationCode":"const args = { timeout: 30 };\nconst json = JSON.stringify(args); // throws on cycles, produces valid JSON\nJSON.parse(json); // pre-validate round-trip","typeGuard":"function isWaitFlowCompletionAction(v: unknown): v is { timeout?: number } {\n  return typeof v === 'object' && v !== null &&\n    (!('timeout' in v) || typeof (v as any).timeout === 'number');\n}","tryCatchPattern":"try {\n  const out = await tool.call('wait_flow_completion', args);\n} catch (err) {\n  if (String(err).includes('failed to parse')) {\n    // regenerate/repair args JSON and retry once\n  }\n}","preventionTips":["Always pass a typed object, let the SDK serialize it","Keep timeout a number, never a string","Validate args against the tool's JSON schema before calling","Retry LLM-generated tool calls once on parse errors"],"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-08T05:18:18.240Z"}