vxcontrol/pentagi · error

failed to unmarshal %s search in memory action arguments: %w

Error message

failed to unmarshal %s search in memory action arguments: %w

What it means

The `search in memory` tool received tool-call arguments that could not be decoded into the `SearchInMemoryAction` struct. The LLM agent produced JSON that fails `json.Unmarshal` (malformed JSON, wrong types, or unknown/misspelled fields with strict typing). This library wraps the underlying decode error so the caller sees both the tool name and the JSON error.

Source

Thrown at backend/pkg/tools/memory.go:63

	}

	ctx, observation := obs.Observer.NewObservation(ctx)
	logger := logrus.WithContext(ctx).WithFields(enrichLogrusFields(m.flowID, nil, nil, logrus.Fields{
		"tool": name,
		"args": string(args),
	}))

	if m.store == nil {
		logger.Error("pgvector store is not initialized")
		return "", fmt.Errorf("pgvector store is not initialized")
	}

	switch name {
	case SearchInMemoryToolName:
		var action SearchInMemoryAction
		if err := json.Unmarshal(args, &action); err != nil {
			logger.WithError(err).Error("failed to unmarshal search in memory action arguments")
			return "", fmt.Errorf("failed to unmarshal %s search in memory action arguments: %w", name, err)
		}

		filters := map[string]any{
			"flow_id":  strconv.FormatInt(m.flowID, 10),
			"doc_type": memoryVectorStoreDefaultType,
		}
		if action.TaskID != nil && *action.TaskID != 0 {
			filters["task_id"] = action.TaskID.String()
		}
		if action.SubtaskID != nil && *action.SubtaskID != 0 {
			filters["subtask_id"] = action.SubtaskID.String()
		}

		isSpecificFilters, globalFilters := getGlobalFilters(filters)
		metadata := langfuse.Metadata{
			"tool_name":        name,
			"message":          action.Message,
			"limit":            memoryVectorStoreResultLimit,

View on GitHub (pinned to ea665308ba)

Solutions

  1. Log and inspect the raw `args` string next to the wrapped error to see exactly what the model produced.
  2. Verify the tool's JSON schema advertised to the LLM matches the current `SearchInMemoryAction` struct fields and types.
  3. Check the inner `%w` error (e.g. `json: cannot unmarshal string into Go struct field ...`) to pinpoint the offending field.
  4. Retry the tool call; if a specific model repeatedly mis-formats arguments, switch provider or strengthen the tool description.
  5. If arguments come from your own code, marshal with `json.Marshal(SearchInMemoryAction{...})` instead of hand-built strings.

Example fix

// before
args := []byte(`{"questions": "what is x"}`) // questions must be an array
// after
args, _ := json.Marshal(SearchInMemoryAction{Questions: []string{"what is x"}})
Defensive patterns

Strategy: validation

Validate before calling

var probe map[string]any
if err := json.Unmarshal(args, &probe); err != nil {
    return fmt.Errorf("invalid tool args JSON: %w", err)
}
q, ok := probe["questions"].([]any)
if !ok || len(q) == 0 {
    return errors.New("questions must be a non-empty array of strings")
}

Type guard

func isValidSearchInMemoryArgs(args []byte) bool {
    var a struct{ Questions []string `json:"questions"` }
    return json.Unmarshal(args, &a) == nil && len(a.Questions) > 0
}

Try / catch

out, err := mem.Handle(ctx, tools.SearchInMemoryToolName, args)
if err != nil {
    var jsonErr *json.UnmarshalTypeError
    if errors.As(err, &jsonErr) {
        logger.Warnf("malformed tool args: %v, raw=%s", err, string(args))
        return retryToolCall(ctx) // ask the model to re-emit arguments
    }
    return err
}

Prevention

When it happens

Trigger: An agent invokes the `search_in_memory` tool via `memory.Handle(ctx, name, args)` with `name == SearchInMemoryToolName` and `args` bytes that json.Unmarshal cannot decode into `SearchInMemoryAction` — e.g. `questions` sent as a string instead of an array, truncated JSON, or a non-string `query` field.

Common situations: LLM providers emitting malformed tool-call JSON; prompt templates that show an outdated action schema; models wrapping arguments in markdown fences or extra nesting; a struct field type changed (e.g. `Questions []string` → string) while the model still emits the old shape.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/8edd226745ce694a. Report an issue: GitHub.