router-for-me/CLIProxyAPI · error

decode host auth save request: %w

Error message

decode host auth save request: %w

What it means

The host's auth.save RPC callback could not decode its request into pluginapi.HostAuthSaveRequest — invalid JSON or wrong field types. Saving is rejected before validateHostAuthSaveRequest even runs.

Source

Thrown at internal/pluginhost/auth_callbacks.go:119

	authIndex := strings.TrimSpace(req.AuthIndex)
	if authIndex == "" {
		return nil, fmt.Errorf("auth_index is required")
	}
	auth, errGet := h.authByIndex(authIndex)
	if errGet != nil {
		return nil, errGet
	}
	entry := h.buildHostAuthFileEntry(auth)
	if entry == nil {
		return nil, fmt.Errorf("auth runtime info not found for auth_index %s", authIndex)
	}
	return marshalRPCResult(pluginapi.HostAuthGetRuntimeResponse{Auth: *entry})
}

func (h *Host) callHostAuthSave(ctx context.Context, request []byte) ([]byte, error) {
	var req pluginapi.HostAuthSaveRequest
	if errUnmarshal := json.Unmarshal(request, &req); errUnmarshal != nil {
		return nil, fmt.Errorf("decode host auth save request: %w", errUnmarshal)
	}
	name, rawJSON, errValidate := validateHostAuthSaveRequest(req)
	if errValidate != nil {
		return nil, errValidate
	}
	path, errSave := h.saveAuthFile(ctx, name, rawJSON)
	if errSave != nil {
		return nil, errSave
	}
	return marshalRPCResult(pluginapi.HostAuthSaveResponse{
		Name: name,
		Path: path,
	})
}

func (h *Host) listAuthFiles() ([]pluginapi.HostAuthFileEntry, error) {
	manager := h.currentAuthManager()
	if manager != nil {

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Log and JSON-validate the exact payload the plugin sends for save
  2. Build the request with the pluginapi types (json.Marshal of a HostAuthSaveRequest) rather than manual strings
  3. Upgrade plugin and host together so both sides share the same pluginapi definitions
  4. Verify transport framing (length prefixes) if payloads arrive truncated
Defensive patterns

Strategy: validation

Validate before calling

// Plugin side: marshal structured types and pre-validate the JSON blob.
raw, err := json.Marshal(authData)
if err != nil { return err }
req := pluginapi.HostAuthSaveRequest{Name: name, JSON: raw}
if !json.Valid(req.JSON) { return errors.New("auth payload not valid JSON") }

Prevention

When it happens

Trigger: Plugin calls host auth save with a malformed payload — non-JSON bytes, wrong types for Name/JSON fields, or a truncated frame; also mismatched pluginapi struct definitions between plugin and host versions.

Common situations: Plugin serializing the auth JSON by string concatenation producing invalid JSON; plugin/host version skew after upgrading one side only; transport framing bug splitting the payload.

Related errors


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