{"record":{"id":"504d045a099e3b3f","repo":"vxcontrol/pentagi","slug":"failed-to-unmarshal-s-search-answer-action-argume","errorCode":null,"errorMessage":"failed to unmarshal %s search answer action arguments: %w","messagePattern":"failed to unmarshal (.+?) search answer action arguments: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/search.go","lineNumber":89,"sourceCode":"\nfunc (s *search) Handle(ctx context.Context, name string, args json.RawMessage) (string, error) {\n\tctx, observation := obs.Observer.NewObservation(ctx)\n\tlogger := logrus.WithContext(ctx).WithFields(enrichLogrusFields(s.flowID, s.taskID, s.subtaskID, logrus.Fields{\n\t\t\"tool\": name,\n\t\t\"args\": string(args),\n\t}))\n\n\tif s.store == nil {\n\t\tlogger.Error(\"pgvector store is not initialized\")\n\t\treturn \"\", fmt.Errorf(\"pgvector store is not initialized\")\n\t}\n\n\tswitch name {\n\tcase SearchAnswerToolName:\n\t\tvar action SearchAnswerAction\n\t\tif err := json.Unmarshal(args, &action); err != nil {\n\t\t\tlogger.WithError(err).Error(\"failed to unmarshal search answer action arguments\")\n\t\t\treturn \"\", fmt.Errorf(\"failed to unmarshal %s search answer action arguments: %w\", name, err)\n\t\t}\n\n\t\tfilters := map[string]any{\n\t\t\t\"doc_type\":    searchVectorStoreDefaultType,\n\t\t\t\"answer_type\": action.Type,\n\t\t}\n\n\t\tmetadata := langfuse.Metadata{\n\t\t\t\"tool_name\":     name,\n\t\t\t\"message\":       action.Message,\n\t\t\t\"limit\":         searchVectorStoreResultLimit,\n\t\t\t\"threshold\":     searchVectorStoreThreshold,\n\t\t\t\"doc_type\":      searchVectorStoreDefaultType,\n\t\t\t\"answer_type\":   action.Type,\n\t\t\t\"queries_count\": len(action.Questions),\n\t\t}\n\n\t\tretriever := observation.Retriever(","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/search.go#L71-L107","documentation":"The `search answer` tool received arguments that failed to decode into `SearchAnswerAction`. As with the memory tool, the raw LLM-emitted JSON did not match the expected struct (fields, types, or overall JSON validity), and the underlying decode error is wrapped with the tool name.","triggerScenarios":"Agent calls the `search answer` tool and `json.Unmarshal(args, &SearchAnswerAction{})` fails — e.g. `questions` not an array of strings, `answer_type` wrong type, truncated or fenced JSON from the model.","commonSituations":"Model emitting the schema of a similar tool (`store answer`) instead; outdated tool description in the prompt; providers with weaker JSON-mode guarantees (local Ollama models); action struct changed without updating the advertised schema.","solutions":["Read the wrapped `%w` error to find the exact field/type mismatch.","Diff the tool JSON schema sent to the model against `SearchAnswerAction`.","Inspect the raw args logged with the error for truncation or markdown fences.","Retry, or constrain the model to JSON mode / a stronger provider if it recurs."],"exampleFix":"// before\nargs := []byte(`{\"questions\":[\"q1\"],\"answer_type\":3}`) // answer_type must be a string\n// after\nargs, _ := json.Marshal(SearchAnswerAction{Questions: []string{\"q1\"}, Type: \"summary\"})","handlingStrategy":"validation","validationCode":"var probe struct {\n    Questions []any  `json:\"questions\"`\n    Type      string `json:\"answer_type\"`\n}\nif err := json.Unmarshal(args, &probe); err != nil {\n    return fmt.Errorf(\"invalid search answer args: %w\", err)\n}\nif len(probe.Questions) == 0 || probe.Type == \"\" {\n    return errors.New(\"questions and answer_type are required\")\n}","typeGuard":"func isValidSearchAnswerArgs(args []byte) bool {\n    var a search.SearchAnswerAction\n    return json.Unmarshal(args, &a) == nil && len(a.Questions) > 0 && a.Type != \"\"\n}","tryCatchPattern":"out, err := searchTool.Handle(ctx, tools.SearchAnswerToolName, args)\nif err != nil {\n    if errors.Is(err, io.ErrUnexpectedEOF) || strings.Contains(err.Error(), \"cannot unmarshal\") {\n        return retryWithSchemaReminder(ctx, args)\n    }\n    return err\n}","preventionTips":["Keep the advertised tool schema in sync with SearchAnswerAction.","Prefer JSON-mode-capable providers for tool calling.","Log raw args on every unmarshal failure to speed diagnosis.","Retry once on malformed tool args before surfacing the error to the agent."],"tags":["json","unmarshal","llm-tool-call","search"],"backgroundTag":"json-unmarshal-type-mismatch","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}