wavetermdev/waveterm · error

failed to decode data URL for text/plain file: %w

Error message

failed to decode data URL for text/plain file: %w

What it means

ExtractTextData decodes text/plain attachments. When the text content is supplied as a data: URL, it uses utilfn.DecodeDataURL to recover the raw bytes; if that decoding fails the error is wrapped and returned. This indicates the data URL itself is malformed (bad base64, missing/invalid media type, corrupt percent-encoding).

Source

Thrown at pkg/aiusechat/aiutil/aiutil.go:94

		return url, nil
	}
	if len(data) > 0 {
		base64Data := base64.StdEncoding.EncodeToString(data)
		return fmt.Sprintf("data:%s;base64,%s", mimeType, base64Data), nil
	}
	return "", fmt.Errorf("file part missing both url and data")
}

// ExtractTextData extracts text data from either Data field or URL field (data: URLs only)
func ExtractTextData(data []byte, url string) ([]byte, error) {
	if len(data) > 0 {
		return data, nil
	}
	if url != "" {
		if strings.HasPrefix(url, "data:") {
			_, decodedData, err := utilfn.DecodeDataURL(url)
			if err != nil {
				return nil, fmt.Errorf("failed to decode data URL for text/plain file: %w", err)
			}
			return decodedData, nil
		}
		return nil, fmt.Errorf("dropping text/plain file with URL (must be fetched and converted to data)")
	}
	return nil, fmt.Errorf("text/plain file part missing data")
}

// FormatAttachedTextFile formats a text file attachment with proper encoding and deterministic suffix
func FormatAttachedTextFile(fileName string, textContent []byte) string {
	if fileName == "" {
		fileName = "untitled.txt"
	}

	encodedFileName := strings.ReplaceAll(fileName, `"`, """)
	quotedFileName := strconv.Quote(encodedFileName)

	textStr := string(textContent)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Regenerate the data URL with a standard encoder, e.g. "data:text/plain;base64," + base64.StdEncoding.EncodeToString(data).
  2. Check the wrapped inner error (err.Unwrap/strings) to see the exact base64/URL parse failure and fix the payload accordingly.
  3. Pass the raw bytes via the data argument instead of a data: URL — that path bypasses decoding entirely.
  4. Verify the URL was not truncated or line-wrapped in transport (config files, logs, databases).

Example fix

// before
url := "data:text/plain;base64," + base64.URLEncoding.EncodeToString(data) // wrong alphabet
b, err := aiutil.ExtractTextData(nil, url) // failed to decode data URL
// after
b, err := aiutil.ExtractTextData(data, "") // pass bytes directly
Defensive patterns

Strategy: validation

Validate before calling

func validDataURL(u string) bool {
    if !strings.HasPrefix(u, "data:") { return false }
    idx := strings.Index(u, "base64,")
    if idx < 0 { return false }
    _, err := base64.StdEncoding.DecodeString(u[idx+len("base64,"):])
    return err == nil
}

Type guard

func isDecodableDataURL(u string) bool { return strings.HasPrefix(u, "data:") && utilfnDecodeOK(u) }

Try / catch

b, err := aiutil.ExtractTextData(data, url)
if err != nil {
    return fmt.Errorf("text attachment unusable: %w", err) // inspect %w for base64 cause
}

Prevention

When it happens

Trigger: Passing a non-empty url with the "data:" prefix to ExtractTextData where DecodeDataURL fails — e.g. base64 payload contains invalid characters, the URL is truncated, or the mediatype portion is malformed.

Common situations: Hand-building data: URLs with manual base64 encoding (wrong encoding name, stray whitespace/newlines); truncation of long data URLs by logs or config; percent-encoded content mangled during copy/paste.

Understand the failure class

Related errors


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