router-for-me/CLIProxyAPI · error

invalid auth json: %w

Error message

invalid auth json: %w

What it means

Wrapped error from validateHostAuthSaveRequest when json.Unmarshal of the submitted JSON into map[string]any fails. The payload is non-empty but syntactically invalid JSON, so it cannot be persisted as an auth file.

Source

Thrown at internal/pluginhost/auth_callbacks.go:276

	}
	return auth, data, nil
}

func validateHostAuthSaveRequest(req pluginapi.HostAuthSaveRequest) (string, []byte, error) {
	name := strings.TrimSpace(req.Name)
	if isUnsafeAuthFileName(name) {
		return "", nil, fmt.Errorf("invalid auth file name")
	}
	if !strings.HasSuffix(strings.ToLower(name), ".json") {
		return "", nil, fmt.Errorf("auth file name must end with .json")
	}
	rawJSON := bytesTrimSpace(req.JSON)
	if len(rawJSON) == 0 {
		return "", nil, fmt.Errorf("json is required")
	}
	var metadata map[string]any
	if errUnmarshal := json.Unmarshal(rawJSON, &metadata); errUnmarshal != nil {
		return "", nil, fmt.Errorf("invalid auth json: %w", errUnmarshal)
	}
	return filepath.Base(name), rawJSON, nil
}

func (h *Host) saveAuthFile(ctx context.Context, name string, data []byte) (string, error) {
	authDir := h.resolvedAuthDir()
	if authDir == "" {
		return "", fmt.Errorf("auth directory is unavailable")
	}
	dst := filepath.Join(authDir, filepath.Base(name))
	if !filepath.IsAbs(dst) {
		if abs, errAbs := filepath.Abs(dst); errAbs == nil {
			dst = abs
		}
	}
	auth, errBuild := h.buildAuthFromFileData(dst, data)
	if errBuild != nil {
		return "", errBuild

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Build the payload with json.Marshal of a struct or map instead of string building
  2. Check the wrapped error's offset (SyntaxError.Offset) to find the invalid character
  3. Validate locally with json.Valid([]byte(req.JSON)) before invoking save

Example fix

// before
req.JSON := fmt.Sprintf("{provider: %s}", p) // unquoted key, invalid

// after
b, _ := json.Marshal(map[string]any{"type": p, "email": e})
req.JSON = string(b)
Defensive patterns

Strategy: validation

Validate before calling

if !json.Valid([]byte(req.JSON)) {
    return fmt.Errorf("payload is not valid JSON")
}

Try / catch

var synErr *json.SyntaxError
if errors.As(err, &synErr) {
    // report synErr.Offset to the payload producer (plugin)
}

Prevention

When it happens

Trigger: Plugin passes a hand-built string, YAML, form-encoded data, or a truncated buffer as req.JSON; double-encoding (a quoted JSON string containing JSON) that does not decode to an object.

Common situations: String concatenation instead of json.Marshal in the plugin; a proxy or transport layer mangling the payload; copy from documentation with smart quotes.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/45c0eefe7994e427. Report an issue: GitHub.