github/github-mcp-server · error

failed to unmarshal JSON text: %w

Error message

failed to unmarshal JSON text: %w

What it means

jsonTextToCSV failed to decode the tool's JSON output text before converting it to CSV. json.Decoder.Decode returns errors like SyntaxError (malformed JSON), UnexpectedEOF (truncated text), or invalid UTF-8 errors when the input is not a complete, single JSON document. This means the upstream tool produced non-JSON text — typically an error message, plain-text output, or a truncated payload — while the server was configured with CSV output format.

Source

Thrown at pkg/github/csv_output.go:114

	}

	csvText, err := jsonTextToCSV(text.Text)
	if err != nil {
		return utils.NewToolResultErrorFromErr("failed to convert response to CSV", err)
	}

	result.Content = []mcp.Content{&mcp.TextContent{Text: csvText}}
	result.StructuredContent = nil
	return result
}

func jsonTextToCSV(text string) (string, error) {
	decoder := json.NewDecoder(strings.NewReader(text))
	decoder.UseNumber()

	var value any
	if err := decoder.Decode(&value); err != nil {
		return "", fmt.Errorf("failed to unmarshal JSON text: %w", err)
	}

	doc := csvDocument(value)
	if len(doc.metadata) == 0 && len(doc.rows) == 0 {
		return "", nil
	}

	var buf bytes.Buffer
	writeCSVMetadata(&buf, doc.metadata)
	if len(doc.rows) == 0 {
		return buf.String(), nil
	}

	headers := csvHeaders(doc.rows)
	if len(headers) == 0 {
		return buf.String(), nil
	}

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Re-run the tool without the CSV output format to see the raw payload and confirm it is JSON
  2. Choose CSV output only for tabular tools (list_* tools returning arrays of objects)
  3. If the payload looks like JSON but still fails, check for truncation (content window limits) or BOM/whitespace prefix
  4. Report tools that emit non-JSON text so they can be made CSV-safe upstream

Example fix

// before
var value any
if err := decoder.Decode(&value); err != nil {
	return "", fmt.Errorf("failed to unmarshal JSON text: %w", err)
}

// after — reject non-JSON early with a payload preview
if !json.Valid([]byte(text)) {
	return "", fmt.Errorf("tool output is not valid JSON (csv conversion aborted): %.120s", text)
}
Defensive patterns

Strategy: validation

Validate before calling

// before requesting CSV conversion, verify the text is a JSON document
func isConvertibleJSON(text string) bool {
	trimmed := strings.TrimSpace(text)
	return strings.HasPrefix(trimmed, "{") || strings.HasPrefix(trimmed, "[")
}

Type guard

func isJSONText(s string) bool { return json.Valid([]byte(s)) }

Try / catch

if err := decoder.Decode(&value); err != nil {
	var syntaxErr *json.SyntaxError
	if errors.As(err, &syntaxErr) {
		// not JSON at all: return the raw text instead of failing the whole tool call
		return text, nil
	}
	return "", fmt.Errorf("failed to unmarshal JSON text: %w", err)
}

Prevention

When it happens

Trigger: Running any tool with output format csv where the tool's textual result is not valid JSON: tools that return plain strings (URLs, plain text), error strings placed in TextContent, or responses truncated by size limits.

Common situations: MCP client requests output format csv for a tool whose content is inherently non-JSON; version changes that made a tool emit human-readable text; empty TextContent from a failed upstream call.

Related errors


AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15). Data as JSON: /api/errors/e281faa69b962977. Report an issue: GitHub.