{"record":{"id":"ae3e6be2cf76f27c","repo":"BoundaryML/baml","slug":"video-is-not-a-url","errorCode":null,"errorMessage":"Video is not a URL","messagePattern":"Video is not a URL","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"engine/language_client_typescript/typescript_src/video.ts","lineNumber":69,"sourceCode":"    const response = await fetch(url);\n    const blob = await response.blob();\n    return BamlVideo.fromBlob(blob);\n  }\n\n  /**\n   * Check if the video is stored as a URL\n   */\n  isUrl(): boolean {\n    return this.type === \"url\";\n  }\n\n  /**\n   * Get the URL of the video if it's stored as a URL\n   * @throws Error if the video is not stored as a URL\n   */\n  asUrl(): string {\n    if (!this.isUrl()) {\n      throw new Error(\"Video is not a URL\");\n    }\n    return this.content;\n  }\n\n  /**\n   * Get the base64 data and media type if the video is stored as base64\n   * @returns [base64Data, mediaType]\n   * @throws Error if the video is not stored as base64\n   */\n  asBase64(): [string, string] {\n    if (this.type !== \"base64\") {\n      throw new Error(\"Video is not base64\");\n    }\n    return [this.content, this.mediaType || \"\"];\n  }\n\n  /**\n   * Convert the video to a JSON representation","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_client_typescript/typescript_src/video.ts#L51-L87","documentation":"Video.asUrl() throws this when the video's content is stored as base64 data rather than as a URL. The class supports two storage representations (URL and base64) and asUrl is only valid for the URL representation. Callers must check isUrl() or use the matching accessor first.","triggerScenarios":"Calling video.asUrl() on a Video constructed with base64 content (e.g. Video.fromBase64 or media built from raw bytes) instead of URL content. Equivalently, calling asUrl() when video.isUrl() returns false.","commonSituations":"Passing inline base64-encoded videos (common in LLM multimodal prompts) to code that assumes all videos are URL-backed; deserializing videos from JSON where the content type was lost; rendering code that blindly calls asUrl() without branching on the storage type.","solutions":["Check video.isUrl() before calling asUrl() and branch to asBase64() for base64 content","Convert the base64 content to a data URI instead of using asUrl()","Pass the video as a URL when constructing it so the URL accessor is valid","Inspect the deserialization path to ensure the content type flag survives round-trips"],"exampleFix":"// before\nconst url = video.asUrl();\n// after\nconst url = video.isUrl() ? video.asUrl() : `data:${video.asBase64()[1]};base64,${video.asBase64()[0]}`;","handlingStrategy":"type-guard","validationCode":"if (!video.isUrl()) {\n  // take the asBase64() path instead\n}","typeGuard":"function isUrlVideo(v) { return typeof v.isUrl === \"function\" && v.isUrl(); }","tryCatchPattern":"let url;\ntry {\n  url = video.asUrl();\n} catch (e) {\n  if (e.message === \"Video is not a URL\") {\n    url = null; // handle base64 case via asBase64()\n  } else {\n    throw e;\n  }\n}","preventionTips":["Always branch on isUrl() before choosing an accessor","Keep the storage representation explicit in your media pipeline (tag videos as 'url' or 'base64')","Add a converter utility that normalizes both representations before consumption"],"tags":["typescript","video","multimodal","content-type"],"backgroundTag":"incompatible-source-type","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}