wavetermdev/waveterm · error

invalid data URL: must start with 'data:'

Error message

invalid data URL: must start with 'data:'

What it means

DecodeDataURL parses data: URLs (RFC 2397) and requires the string to start with the literal prefix "data:". Any string without it — a plain https URL, base64 blob, or malformed input — is rejected immediately with this error before any further parsing.

Source

Thrown at pkg/util/utilfn/marshal.go:171

	// If field is pointer and value isn't already a pointer, try address
	if field.Kind() == reflect.Ptr && valueRef.Kind() != reflect.Ptr {
		return setValue(field, valueRef.Addr().Interface())
	}

	// Try conversion if types are convertible
	if valueRef.Type().ConvertibleTo(field.Type()) {
		field.Set(valueRef.Convert(field.Type()))
		return nil
	}

	return fmt.Errorf("cannot set value of type %v to field of type %v", valueRef.Type(), field.Type())
}

// DecodeDataURL decodes a data URL and returns the mimetype and raw data bytes
func DecodeDataURL(dataURL string) (mimeType string, data []byte, err error) {
	if !strings.HasPrefix(dataURL, "data:") {
		return "", nil, fmt.Errorf("invalid data URL: must start with 'data:'")
	}

	parts := strings.SplitN(dataURL, ",", 2)
	if len(parts) != 2 {
		return "", nil, fmt.Errorf("invalid data URL format: missing comma separator")
	}

	header := parts[0]
	dataStr := parts[1]

	// Parse mimetype from header: "data:text/plain;base64" -> "text/plain"
	headerWithoutPrefix := strings.TrimPrefix(header, "data:")
	mimeType = strings.Split(headerWithoutPrefix, ";")[0]
	if mimeType == "" {
		mimeType = "text/plain" // default mimetype
	}

	if strings.Contains(header, ";base64") {

View on GitHub (pinned to a4447c1563)

Solutions

  1. Check strings.HasPrefix(dataURL, "data:") before calling, and route non-data URLs to an HTTP fetch path instead
  2. If you have raw bytes/mime, construct a proper data URL: fmt.Sprintf("data:%s;base64,%s", mime, base64.StdEncoding.EncodeToString(data))
  3. Strip whitespace/BOM that may precede the scheme after extraction
  4. Return a clearer user-facing message distinguishing 'remote URL' from 'inline data expected'

Example fix

// before
mime, data, err := utilfn.DecodeDataURL("https://example.com/img.png") // invalid data URL
// after
u := strings.TrimSpace(url)
if !strings.HasPrefix(u, "data:") {
    return fmt.Errorf("expected inline data URL, got %q; fetch remote URLs separately", u)
}
mime, data, err := utilfn.DecodeDataURL(u)
Defensive patterns

Strategy: validation

Validate before calling

func isDataURL(s string) bool {
    return strings.HasPrefix(strings.TrimSpace(s), "data:")
}

Type guard

func isDataURL(s string) bool {
    return strings.HasPrefix(strings.TrimSpace(s), "data:")
}

Try / catch

mime, data, err := utilfn.DecodeDataURL(u)
if err != nil && strings.Contains(err.Error(), "must start with 'data:'") {
    // route to HTTP fetch or wrap bytes into a data URL
}

Prevention

When it happens

Trigger: Passing an http(s):// URL instead of an inlined data URL; passing raw base64 without the data:[mime][;base64], prefix; empty strings from upstream extraction returning nothing; content stored in a DB without the scheme.

Common situations: LLM/tool-message pipelines (ConvertToolResultsToGeminiChatMessage, ExtractTextData) where attachments are sometimes URLs and sometimes data URLs; users pasting image links where inline data was expected; truncation losing the "data:" prefix.

Related errors


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