{"record":{"id":"be5fd5441dcbdc88","repo":"wavetermdev/waveterm","slug":"invalid-uuid-format","errorCode":null,"errorMessage":"Invalid UUID format","messagePattern":"Invalid UUID format","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"pkg/web/webvdomproto.go","lineNumber":31,"sourceCode":"\t\"github.com/wavetermdev/waveterm/pkg/wshrpc\"\n\t\"github.com/wavetermdev/waveterm/pkg/wshrpc/wshclient\"\n\t\"github.com/wavetermdev/waveterm/pkg/wshrpc/wshserver\"\n\t\"github.com/wavetermdev/waveterm/pkg/wshutil\"\n)\n\n// Add the new handler function\nfunc handleVDom(w http.ResponseWriter, r *http.Request) {\n\t// Extract UUID and path from URL\n\tpathParts := strings.Split(strings.TrimPrefix(r.URL.Path, \"/vdom/\"), \"/\")\n\tif len(pathParts) < 1 {\n\t\thttp.Error(w, \"Invalid VDOM URL format\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tuuid := pathParts[0]\n\t// Simple UUID validation\n\tif len(uuid) != 36 {\n\t\thttp.Error(w, \"Invalid UUID format\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\t// Reconstruct the remaining path\n\tpath := \"/\" + strings.Join(pathParts[1:], \"/\")\n\tif r.URL.RawQuery != \"\" {\n\t\tpath += \"?\" + r.URL.RawQuery\n\t}\n\n\t// Read request body if present\n\tvar body []byte\n\tvar err error\n\tif r.Body != nil {\n\t\tbody, err = io.ReadAll(r.Body)\n\t\tif err != nil {\n\t\t\thttp.Error(w, fmt.Sprintf(\"Error reading request body: %v\", err), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/web/webvdomproto.go#L13-L49","documentation":"handleVDom validates that the first path segment after /vdom/ is exactly 36 characters (a UUID). If not, pkg/web/webvdomproto.go:31 returns HTTP 400 'Invalid UUID format'. This is a length-only check, so any 36-char token passes even if not a real UUID.","triggerScenarios":"Calling the /vdom/ endpoint with a block/route id whose first path segment is not 36 characters — empty id, truncated id, numeric id, or an id with surrounding whitespace.","commonSituations":"Passing a Wave block ID variant instead of the full UUID, a partially-constructed URL like /vdom//render (empty first segment), copy-pasting an id that was trimmed or truncated by logs, or using a pre-UUID identifier from an older version.","solutions":["Print/log the URL path on the client before the request and confirm the first segment after /vdom/ is exactly 36 characters.","Obtain the correct UUID from the source of truth (block metadata / block controller) rather than a user-supplied or derived string.","Trim whitespace and strip any surrounding brackets or quotes from the id before building the URL.","If you control ids, generate them with a UUID v4 library so they are always 36 chars."],"exampleFix":"// before\nconst url = `/vdom/${shortId}/render`\n\n// after\nif (blockId.length !== 36) throw new Error(`bad vdom id: ${blockId}`)\nconst url = `/vdom/${encodeURIComponent(blockId)}/render`","handlingStrategy":"validation","validationCode":"if (typeof blockId !== \"string\" || blockId.length !== 36) {\n  throw new Error(`invalid vdom uuid: ${blockId}`);\n}\nconst resp = await fetch(`/vdom/${blockId}/${path}`);","typeGuard":"function isVdomUuid(id) {\n  return typeof id === \"string\" && id.length === 36;\n}","tryCatchPattern":"if (!isVdomUuid(blockId)) throw new Error(\"invalid uuid before request\");\nconst resp = await fetch(`/vdom/${blockId}/render`);\nif (resp.status === 400) throw new Error(await resp.text());","preventionTips":["Validate id length (36 chars) client-side before building /vdom/ URLs.","Take block ids from the block registry, not from user input or truncated logs.","Trim whitespace and strip brackets from ids copied from UI/log output."],"tags":["go","http","uuid","validation"],"backgroundTag":"invalid-uuid-format","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}