wavetermdev/waveterm · error

failed to decode base64 data: %w

Error message

failed to decode base64 data: %w

What it means

When a text/plain file part arrives as a data: URL, the converter base64-decodes the payload to build an Anthropic plain-text document source. This error wraps the base64.StdEncoding.DecodeString failure, meaning the payload after the comma is not valid standard base64 (bad characters, wrong padding, URL-safe alphabet, or percent-encoded/URL-encoded content).

Source

Thrown at pkg/aiusechat/anthropic/anthropic-convertmessage.go:437

				Source: &anthropicSource{
					Type: "url",
					URL:  p.URL,
				},
			}, nil
		}

	case p.MediaType == "text/plain":
		// text/plain → Anthropic document block, but NO URL form supported
		if strings.HasPrefix(p.URL, "data:") {
			// Data URL → decode base64 data and return as document with PlainTextSource
			parts := strings.SplitN(p.URL, ",", 2)
			if len(parts) != 2 {
				return nil, errors.New("invalid data URL format")
			}
			// Decode base64 data
			textData, err := base64.StdEncoding.DecodeString(parts[1])
			if err != nil {
				return nil, fmt.Errorf("failed to decode base64 data: %w", err)
			}
			return &anthropicMessageContentBlock{
				Type: "document",
				Source: &anthropicSource{
					Type:      "text",
					Data:      string(textData),
					MediaType: "text/plain",
				},
			}, nil
		} else {
			// HTTP/HTTPS URL → not supported inline, would need to fetch
			return nil, fmt.Errorf("dropping text/plain file with URL (must be fetched and converted to base64 or uploaded to Files API)")
		}

	default:
		// Other media types → not supported inline, must upload and use file_id
		return nil, fmt.Errorf("dropping file with unsupported media type '%s' (must be uploaded to Files API and sent as file_id)", p.MediaType)
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Regenerate the data URL with standard base64 (btoa in JS, base64.StdEncoding in Go)
  2. Strip whitespace/newlines from the base64 payload before sending
  3. If the payload is URL-safe base64, convert it to standard base64 (replace - and _ with + and /, pad with =)
  4. Verify the data URL format is data:text/plain;base64,<payload> with the ;base64 marker handled upstream

Example fix

// before
url := "data:text/plain;base64," + urlSafeBase64(text) // URL-safe alphabet, padding issues
// after
url := "data:text/plain;base64," + base64.StdEncoding.EncodeToString([]byte(text))
Defensive patterns

Strategy: validation

Validate before calling

func validStdBase64(s string) bool {
    _, err := base64.StdEncoding.DecodeString(s)
    return err == nil
}
// extract payload from data URL, then: if !validStdBase64(payload) { normalize or reject }

Type guard

func isStdBase64(s string) bool {
    _, err := base64.StdEncoding.DecodeString(s)
    return err == nil
}

Try / catch

if _, err := convert(msg); err != nil {
    if strings.Contains(err.Error(), "failed to decode base64") {
        normalized := strings.NewReplacer("-", "+", "_", "/", "\n", "", "\r", "", " ", "").Replace(payload)
        return convert(rebuildDataURL(normalized))
    }
    return err
}

Prevention

When it happens

Trigger: Sending a text/plain part whose data: URL payload was produced with base64.URL_ENCODING, is truncated, contains whitespace/newlines, or is actually URL-encoded plain text rather than base64.

Common situations: Frontends encoding text with encodeURIComponent instead of btoa; double-encoding when the data URL was itself JSON-escaped; copying a data URL and dropping characters; mixing URL-safe and standard base64.

Understand the failure class

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/06561acee72d6751. Report an issue: GitHub.