{"record":{"id":"c54e9897231e889b","repo":"wavetermdev/waveterm","slug":"invalid-data-url-must-start-with-data","errorCode":null,"errorMessage":"invalid data URL: must start with 'data:'","messagePattern":"invalid data URL: must start with 'data:'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/utilfn/marshal.go","lineNumber":171,"sourceCode":"\n\t// If field is pointer and value isn't already a pointer, try address\n\tif field.Kind() == reflect.Ptr && valueRef.Kind() != reflect.Ptr {\n\t\treturn setValue(field, valueRef.Addr().Interface())\n\t}\n\n\t// Try conversion if types are convertible\n\tif valueRef.Type().ConvertibleTo(field.Type()) {\n\t\tfield.Set(valueRef.Convert(field.Type()))\n\t\treturn nil\n\t}\n\n\treturn fmt.Errorf(\"cannot set value of type %v to field of type %v\", valueRef.Type(), field.Type())\n}\n\n// DecodeDataURL decodes a data URL and returns the mimetype and raw data bytes\nfunc DecodeDataURL(dataURL string) (mimeType string, data []byte, err error) {\n\tif !strings.HasPrefix(dataURL, \"data:\") {\n\t\treturn \"\", nil, fmt.Errorf(\"invalid data URL: must start with 'data:'\")\n\t}\n\n\tparts := strings.SplitN(dataURL, \",\", 2)\n\tif len(parts) != 2 {\n\t\treturn \"\", nil, fmt.Errorf(\"invalid data URL format: missing comma separator\")\n\t}\n\n\theader := parts[0]\n\tdataStr := parts[1]\n\n\t// Parse mimetype from header: \"data:text/plain;base64\" -> \"text/plain\"\n\theaderWithoutPrefix := strings.TrimPrefix(header, \"data:\")\n\tmimeType = strings.Split(headerWithoutPrefix, \";\")[0]\n\tif mimeType == \"\" {\n\t\tmimeType = \"text/plain\" // default mimetype\n\t}\n\n\tif strings.Contains(header, \";base64\") {","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/util/utilfn/marshal.go#L153-L189","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check strings.HasPrefix(dataURL, \"data:\") before calling, and route non-data URLs to an HTTP fetch path instead","If you have raw bytes/mime, construct a proper data URL: fmt.Sprintf(\"data:%s;base64,%s\", mime, base64.StdEncoding.EncodeToString(data))","Strip whitespace/BOM that may precede the scheme after extraction","Return a clearer user-facing message distinguishing 'remote URL' from 'inline data expected'"],"exampleFix":"// before\nmime, data, err := utilfn.DecodeDataURL(\"https://example.com/img.png\") // invalid data URL\n// after\nu := strings.TrimSpace(url)\nif !strings.HasPrefix(u, \"data:\") {\n    return fmt.Errorf(\"expected inline data URL, got %q; fetch remote URLs separately\", u)\n}\nmime, data, err := utilfn.DecodeDataURL(u)","handlingStrategy":"validation","validationCode":"func isDataURL(s string) bool {\n    return strings.HasPrefix(strings.TrimSpace(s), \"data:\")\n}","typeGuard":"func isDataURL(s string) bool {\n    return strings.HasPrefix(strings.TrimSpace(s), \"data:\")\n}","tryCatchPattern":"mime, data, err := utilfn.DecodeDataURL(u)\nif err != nil && strings.Contains(err.Error(), \"must start with 'data:'\") {\n    // route to HTTP fetch or wrap bytes into a data URL\n}","preventionTips":["Branch on URL scheme: fetch remote URLs, decode data URLs","Trim whitespace/BOM from extracted content before parsing","Encode raw bytes with mime+base64 into proper data: URLs when inlining"],"tags":["data-url","parsing","validation","go"],"backgroundTag":"invalid-data-url","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}