{"record":{"id":"7bf22617c053fdb9","repo":"calesthio/OpenMontage","slug":"invalid-project-id","errorCode":null,"errorMessage":"invalid project id","messagePattern":"invalid project id","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"backlot/server.py","lineNumber":314,"sourceCode":"    # loaded, and browsers heuristically cache /ui assets. no-cache forces a\n    # conditional revalidation (cheap 304 via ETag) on every load so UI fixes\n    # show up on a plain refresh. Media/thumb responses keep normal caching.\n    @app.middleware(\"http\")\n    async def ui_no_cache(request, call_next):\n        response = await call_next(request)\n        path = request.url.path\n        if path == \"/\" or path.startswith(\"/ui\") or path.startswith(\"/p/\"):\n            response.headers[\"Cache-Control\"] = \"no-cache\"\n        return response\n\n    return app\n\n\ndef _safe_project_dir(project_id: str) -> Path:\n    # ':' rejects Windows drive-relative ids like \"C:\" (PROJECTS_DIR / \"C:\"\n    # collapses back to PROJECTS_DIR itself).\n    if any(c in project_id for c in \"/\\\\:\") or project_id in (\".\", \"..\"):\n        raise HTTPException(status_code=400, detail=\"invalid project id\")\n    project_dir = PROJECTS_DIR / project_id\n    if not project_dir.is_dir():\n        raise HTTPException(status_code=404, detail=f\"unknown project: {project_id}\")\n    return project_dir\n\n\ndef _sse(payload: dict) -> str:\n    return f\"data: {json.dumps(payload)}\\n\\n\"\n\n\ndef _thumbnail_for(source: Path, width: int) -> Optional[Path]:\n    \"\"\"Downscale an image (or extract a video poster frame) to a cached JPEG.\"\"\"\n    suffix = source.suffix.lower()\n    is_image = suffix in {\".png\", \".jpg\", \".jpeg\", \".webp\", \".gif\"}\n    is_video = suffix in {\".mp4\", \".webm\", \".mov\"}\n    if not (is_image or is_video):\n        return None\n    try:","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/backlot/server.py#L296-L332","documentation":"The reference image decodes fine but its width or height falls outside the 300–6000 pixel window that Ark accepts for reference images. Both dimensions must independently be within [300, 6000]; tiny thumbnails and oversized panos are both rejected.","triggerScenarios":"A 128x128 icon/thumbnail as a character reference; a 8000x4000 stitched panorama; a 250px-wide cropped detail.","commonSituations":"Using favicon-scale or emoji-scale images as identity references; feeding print-resolution scans without downsampling; automatic thumbnail exports from a CMS.","solutions":["Upscale small images or pick a larger source (>=300px each side).","Downscale large images so the longest side is <=6000px (e.g. PIL thumbnail).","Pick a source image already in a normal photo range (roughly 512–4096px) to satisfy both this and the ratio check."],"exampleFix":"# before\ninputs = {\"reference_image_path\": \"tiny_128.png\"}\n# after\nfrom PIL import Image\nimg = Image.open(\"tiny_128.png\")\nimg = img.resize((max(512, img.width), max(512, img.height)))\nimg.save(\"ref_ok.png\")\ninputs = {\"reference_image_path\": \"ref_ok.png\"}","handlingStrategy":"validation","validationCode":"from PIL import Image\nwith Image.open(ref_path) as im:\n    w, h = im.size\nassert 300 <= w <= 6000 and 300 <= h <= 6000, (w, h)","typeGuard":"def size_ok(w: int, h: int) -> bool:\n    return 300 <= w <= 6000 and 300 <= h <= 6000","tryCatchPattern":"try:\n    tool.run(inputs)\nexcept ValueError as e:\n    if \"300 to 6000\" in str(e):\n        resize_into_range(ref_path)  # thumbnail() or upscale as needed, retry\n        tool.run(inputs)\n    else:\n        raise","preventionTips":["Normalize reference images to a standard box (e.g. longest side 1024-2048px) at ingest.","Reject favicon-scale and print-scale assets at the schema level."],"tags":["python","validation","image-dimensions","reference","seedance"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}