chenhg5/cc-connect · info

gemini stt: marshal request

Error message

gemini stt: marshal request: %w

What it means

Thrown by GeminiSTT.Transcribe in core/speech.go when json.Marshal fails while serializing the Gemini generateContent request body. json.Marshal on a plain anonymous struct built from strings/bytes essentially never fails in practice, so this error indicates an extraordinary serialization failure (e.g. unsupported value introduced by future code changes).

Solutions

  1. If it occurs, inspect the wrapped json error naming the offending field/type.
  2. Review recent changes to the reqBody struct in GeminiSTT.Transcribe for unmarshalable types (chan, func, cycles).
  3. Replace unsupported fields with marshalable equivalents ([]byte, string, etc.).

Example fix

// before
InlineData{MIMEType: "audio/mp3", Data: ch} // ch is a channel: unmarshalable
// after
InlineData{MIMEType: "audio/mp3", Data: audioBytes} // []byte, marshalable
Defensive patterns

Strategy: try-catch

Try / catch

text, err := stt.Transcribe(ctx, audio)
if err != nil {
    if strings.Contains(err.Error(), "marshal request") {
        slog.Error("gemini stt: request serialization failed", "err", err)
        return "", err // genuine bug: fail fast
    }
    return err
}

Prevention

When it happens

Trigger: json.Marshal(reqBody) returns an error — practically only if reqBody ever contains a value that cannot be marshaled (channel, func, cyclic reference) after future modifications; not reachable with the current fixed struct.

Common situations: Essentially never hit by users of the current code; would surface only after a developer adds a field with an unmarshalable type to the Gemini request struct.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/f0a02f047389af87. Report an issue: GitHub.

Appendix: source

Thrown at core/speech.go:254

			{
				"parts": []map[string]any{
					{
						"inline_data": map[string]any{
							"mime_type": mime,
							"data":      b64,
						},
					},
					{
						"text": prompt,
					},
				},
			},
		},
	}

	jsonData, err := json.Marshal(reqBody)
	if err != nil {
		return "", fmt.Errorf("gemini stt: marshal request: %w", err)
	}

	apiURL := fmt.Sprintf("%s/models/%s:generateContent", g.BaseURL, url.PathEscape(g.Model))
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(jsonData))
	if err != nil {
		return "", fmt.Errorf("gemini stt: create request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-goog-api-key", g.APIKey)

	resp, err := g.Client.Do(req)
	if err != nil {
		return "", fmt.Errorf("gemini stt: request: %w", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {

View on GitHub (pinned to 4000b2338a)