googleapis/mcp-toolbox · error · Error

Input for ${paramName} must be a JSON array (e.g., ["a", "b"

Error message

Input for ${paramName} must be a JSON array (e.g., ["a", "b"]).

What it means

A "mapValue" must be a map containing a "fields" key whose value is itself a map. If the shape check fails, this error is returned. This mirrors Firestore's REST representation of maps.

Source

Thrown at internal/server/static/js/runTool.js:138

/**
 * Parses and validates a single array parameter from a raw string value.
 * @param {string} rawValue The raw string value from FormData.
 * @param {string} valueType The full array type string (e.g., "array<number>").
 * @param {string} paramName The name of the parameter for error messaging.
 * @return {!Array<*>} The parsed array.
 * @throws {Error} If parsing or type validation fails.
 */
function parseArrayParameter(rawValue, valueType, paramName) {
    const ELEMENT_TYPE = valueType.substring(6, valueType.length - 1);
    let parsedArray;
    try {
        parsedArray = JSON.parse(rawValue);
    } catch (e) {
        throw new Error(`Invalid JSON format for ${paramName}. Expected an array. ${e.message}`);
    }

    if (!Array.isArray(parsedArray)) {
        throw new Error(`Input for ${paramName} must be a JSON array (e.g., ["a", "b"]).`);
    }

    return parsedArray.map((item, index) => {
        switch (ELEMENT_TYPE) {
            case 'number':
                const NUM = Number(item);
                if (isNaN(NUM)) {
                    throw new Error(`Invalid number "${item}" found in array for ${paramName} at index ${index}.`);
                }
                return NUM;
            case 'boolean':
                return item === true || String(item).toLowerCase() === 'true';
            case 'string':
            default:
                return item;
        }
    });
}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Nest the fields: {"mapValue": {"fields": {<name>: <typedValue>}}}.
  2. Ensure "fields" is a JSON object, not an array or scalar.
  3. Alternatively pass a plain Go map (without the typed wrapper) and let convertPlainMap handle it via the default branch.

Example fix

// before
{"mapValue": {"a": 1}}
// after
{"mapValue": {"fields": {"a": {"integerValue": 1}}}}
Defensive patterns

Strategy: type-guard

Validate before calling

func validMapValue(v any) bool {
    m, ok := v.(map[string]any); if !ok { return false }
    _, ok = m["fields"].(map[string]any); return ok
}

Type guard

func asMapValue(v any) (map[string]any, bool) {
    m, ok := v.(map[string]any); if !ok { return nil, false }
    f, ok := m["fields"].(map[string]any); return f, ok
}

Try / catch

if _, err := JSONToFirestoreValue(val, client); err != nil {
    if strings.Contains(err.Error(), "invalid map value format") { /* nest fields under "fields" */ }
}

Prevention

When it happens

Trigger: Passing {"mapValue": {"a": 1}} (fields directly under mapValue without the "fields" key), {"mapValue": {"fields": [1,2]}} (fields is an array), or {"mapValue": 42} (not a map).

Common situations: Hand-built payloads omitting the "fields" wrapper; nested objects serialized from structs that don't match Firestore's REST shape.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/e88379fed9f97a13. Report an issue: GitHub.