{"record":{"id":"86f9136e90a14f8b","repo":"JuliusBrussee/caveman","slug":"unsupported-image-token-profile","errorCode":null,"errorMessage":"unsupported image token profile","messagePattern":"unsupported image token profile","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/pixel/transform_gemini.go","lineNumber":1004,"sourceCode":"\t\timgs, err = RenderTextToPNGsMultiCol(text, effectiveCols, effectiveNumCols)\n\t} else if style == (RenderStyle{}) {\n\t\timgs, err = RenderTextToPNGs(text, effectiveCols, RenderStyle{})\n\t} else {\n\t\timgs, err = RenderTextToPNGsWithCharLimit(text, effectiveCols, maxCharsPerImage, style, MaxHeightPx, \"\")\n\t}\n\tif err != nil {\n\t\treturn geminiRenderResult{}, err\n\t}\n\tres := geminiRenderResult{droppedCodepoints: make(map[rune]int)}\n\tfor _, img := range imgs {\n\t\tb64 := base64.StdEncoding.EncodeToString(img.PNG)\n\t\tres.parts = append(res.parts, geminiPart{InlineData: &geminiInlineData{MimeType: \"image/png\", Data: b64}})\n\t\tres.imageCount++\n\t\tres.imageBytes += len(img.PNG)\n\t\tres.imagePixels += img.Width * img.Height\n\t\ttokens, supported := engineimage.EstimateTokensForModel(\"gemini\", model, mediaResolution, img.Width, img.Height)\n\t\tif !supported {\n\t\t\treturn geminiRenderResult{}, errors.New(\"unsupported image token profile\")\n\t\t}\n\t\tres.imageTokens += int(math.Ceil(float64(tokens) * ImageCostSafetyMargin))\n\t\tres.droppedChars += img.DroppedChars\n\t\tfor cp, n := range img.DroppedCodepoints {\n\t\t\tres.droppedCodepoints[cp] += n\n\t\t}\n\t}\n\treturn res, nil\n}\n\nfunc evalGeminiProfitability(model, mediaResolution, text string, cols, imageCountCap, numCols int, charsPerToken, priorWarmTokens, priorWarmImageTokens float64, shrinkWidth bool, maxCharsPerImage int, dense bool) *geminiGateEval {\n\tif text == \"\" {\n\t\treturn nil\n\t}\n\tcpt := charsPerToken\n\tif !isFinitePositive(cpt) {\n\t\tcpt = CharsPerToken\n\t}","sourceCodeStart":986,"sourceCodeEnd":1022,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/engine/pixel/transform_gemini.go#L986-L1022","documentation":"While building Gemini inline image parts, the renderer calls engineimage.EstimateTokensForModel(\"gemini\", model, mediaResolution, w, h) per image to cost the request. If that (model, mediaResolution) combination has no token-estimation profile, estimation returns supported=false and rendering aborts: the pipeline refuses to emit images whose cost it cannot account for.","triggerScenarios":"Passing a model string the estimator does not recognize (new, renamed, or misspelled Gemini model id), or a mediaResolution value outside the known set, together with a render that actually produces at least one image.","commonSituations":"Upgrading to a newly released Gemini model before the estimator table knows it; typo'd model name from config; passing an empty model that falls back to an unrecognized default; unusual media_resolution enum values from client config.","solutions":["Check the model id spelling against the estimator's supported list (engineimage package)","Use a known mediaResolution value for that model","If the model is genuinely new, add its token profile to engineimage or fall back to text-only rendering for unsupported models"],"exampleFix":"// before\nres, err := renderGeminiInlineDataParts(\"gemini-9-ultra\", \"media_hi\", text, ...) // unknown model\n\n// after\n// use a model id the estimator supports, or gate image rendering:\nif !engineimage.ModelSupported(\"gemini\", model, mediaResolution) {\n    // render text-only path\n}\nres, err := renderGeminiInlineDataParts(model, mediaResolution, text, ...)","handlingStrategy":"validation","validationCode":"// verify the (model, mediaResolution) pair is estimable before rendering with images\nif _, ok := engineimage.EstimateTokensForModel(\"gemini\", model, mediaResolution, 1, 1); !ok {\n    // use a supported model/resolution or the text-only path\n}","typeGuard":"func imageProfileSupported(model, res string) bool {\n    _, ok := engineimage.EstimateTokensForModel(\"gemini\", model, res, 1, 1)\n    return ok\n}","tryCatchPattern":"res, err := renderGeminiInlineDataParts(model, res0, ...)\nif err != nil && strings.Contains(err.Error(), \"unsupported image token profile\") {\n    // fall back to text-only rendering\n}","preventionTips":["Pin model ids to ones the estimator table knows","Re-check supported profiles when upgrading the engine or models","Validate mediaResolution against the documented enum"],"tags":["pixel","go","gemini","token-estimation","images"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}