# Troubleshooting dsh-request-image-cap Checked on: DSH 0.1.5-rc.1 (the request seam also exists on 0.2.1-rc.5), plugin 0.1.0. **Start here.** Ask your agent to load the `image-cap-doctor` skill (copy it into `~/.dsh/skills/` first, see [the skill section](#skill)), or follow section 0. The plugin has no routes, tools or UI; its state is visible in the DSH log. Messages and their meaning: [ERRORS.md](ERRORS.md). ## Quick index | # | Symptom (what you see) | Most likely cause | Jump | |---|---|---|---| | 1 | A long chat fails with HTTP 400 "image dimensions exceed max allowed size for many-image requests: 2000 pixels", on every retry | plugin not active, or cap above 2000 | [1](#t-400-many-image) | | 2 | DSH logs "readImageRequest is missing", images go out uncapped | DSH update renamed the seam | [2](#t-seam-missing) | | 3 | The plugin entry fails at start with "maxDimension must be an integer ..." | config value of the wrong type | [3](#t-bad-config) | | 4 | The model says screenshots are too small or blurry to read | cap too low for the content | [4](#t-blurry) | | 5 | Other image errors (too many images, image too large in bytes, other providers) | a different limit, not this plugin's | [5](#t-other-limits) | ## 0. Collect facts (read-only, always safe) ```bash dsh --version D="${DSH_HOME:-$HOME/.dsh}/profiles/web" node -e 'const p=require(process.argv[1]);console.log((p.dsh?.profile?.bundles||[]).filter(b=>/image-cap/.test(b)))' "$D/package.json" grep -n -A6 'id: request-image-cap' "$D/cordis.patch.yml" # profile override row, if any journalctl -u --since today | grep 'request-image-cap' | tail -20 ``` Healthy: `request-image-cap: active, 2000px per side` once per DSH start. With `verbose: true`, one line per clamped image: `request-image-cap: 828x5059 -> pixel budget ...`. ## 1. HTTP 400 "image dimensions exceed max allowed size for many-image requests" Anthropic's Messages API accepts larger images in a short request but only 2000 px per side once a request carries many images. DSH limits images by AREA, so a tall full-page screenshot passes DSH's gate and is sent at full height. The failure appears late in a long session and then repeats on every retry, because the image is already in the history. **Likely causes** 1. The plugin is not mounted or not restarted since install (no `active` line, see C1). 2. `enabled: false`, or `maxDimension` set above 2000 in the profile row. 3. The seam was renamed by a DSH update ([2](#t-seam-missing)). 4. The image reaches the provider through a path that does not use the attachment seam (for example a tool result that embeds raw base64 itself). **Diagnose:** section 0. `active` line present with a value at or under 2000 and the error persists = cause 4: note which message index the error names and look at that message's source. **Fix** - Causes 1 and 2: install/enable, cap 2000 or lower, restart `dsh web` **[HUMAN]**. The plugin acts at request time, so the SAME chat becomes sendable again: no need to start over. - Cause 4: report it to the tool's author; meanwhile avoid that tool in long chats. **Verify:** retry the failed turn; with `verbose: true` the log shows the clamp line. ## 2. "attachments.readImageRequest is missing, images are transmitted uncapped" The plugin wraps `ctx.attachments.readImageRequest`. If a DSH update renames or moves it, the plugin logs this warning and stays inert on purpose (it never blocks the boot). **Fix:** update the plugin to a version that supports your DSH line. Until then, long image-heavy chats can hit [1](#t-400-many-image) again. ## 3. Entry fails with "maxDimension must be an integer from 64 through 8192" (or "enabled and verbose must be booleans") **Cause:** a quoted value in YAML (`maxDimension: "2000"`), a float, or a value out of range. **Fix:** unquoted integer 64..8192, booleans unquoted: ```yaml - id: request-image-cap config: enabled: true maxDimension: 2000 verbose: false ``` **Verify:** the `active` line shows the value after the next start (or live reload of the profile patch). ## 4. The model cannot read small text in screenshots The cap shrinks only the copy sent to the model (stored files are untouched), keeping the aspect ratio: a very tall page at 2000 px height becomes narrow. **Fix:** crop or split tall screenshots before attaching them, rather than raising the cap above the provider's limit. ## 5. Other image errors This plugin enforces ONE rule: pixels per side. It does not change the number of images per request, the byte size per image, or limits of other providers. Read the provider's error text: count limits need fewer images in the context (compact or start a new chat), byte limits need DSH's own attachment settings. ## The doctor skill This version does not register its skill automatically; copy it once: ```bash P=$(node -p "require('path').dirname(require.resolve('dsh-request-image-cap/package.json',{paths:[(process.env.DSH_HOME||require('os').homedir()+'/.dsh')+'/profiles/web']}))") mkdir -p "${DSH_HOME:-$HOME/.dsh}/skills" && cp -r "$P/skills/image-cap-doctor" "${DSH_HOME:-$HOME/.dsh}/skills/" ``` ## Common install problems on DSH Placeholders: `DSH_HOME` defaults to `~/.dsh`, the profile is `web`. Items that cannot apply to this plugin (routes, UI, webhooks, media) are left out; numbering follows the shared standard. ### C1. The plugin does not appear at all (no `active` line) **Causes:** (1) installed but not in the profile's bundle list; (2) in the list but `dsh web` not restarted; (3) DSH refused it as incompatible (engines or peer range); (4) its entry threw at start (see [3](#t-bad-config)). **Diagnose** ```bash D="${DSH_HOME:-$HOME/.dsh}/profiles/web" node -e 'const p=require(process.argv[1]);console.log((p.dsh?.profile?.bundles||[]).join("\n"))' "$D/package.json" | grep -n 'dsh-request-image-cap' || echo "NOT IN BUNDLES" ls -la "$D/node_modules/dsh-request-image-cap" 2>/dev/null || echo "NOT INSTALLED" dsh --profile web --dump-config 2>/dev/null | grep -n 'request-image-cap' | head # composed tree, does not boot journalctl -u --since "1 hour ago" | grep -i -E 'image-cap|incompatible|skipped|exemption|duplicate loader entry' | tail -40 ``` **Fix:** `dsh plugin --profile web add ` (adds it to `dsh.profile.bundles` because the package declares `dsh.bundle`), then restart `dsh web` **[HUMAN if your chat runs inside dsh web]**. The package's own patch inserts the entry: do not add a second `insert` row by hand (DSH reports `duplicate loader entry id`); use a plain `- id: request-image-cap` row with `config:` to override values. If the log says the bundle was skipped as incompatible, update the plugin; DSH 0.2.x also offers an exact-version exemption (`dsh plugin allow-version`, see the log message), granted again after every DSH version change. ### C3. Settings do not apply There is no settings form on either DSH line: values come from the package patch, overridden by a `- id: request-image-cap` row in your profile's `cordis.patch.yml`. A section in `settings.yaml` is not read. Back up the file before editing it. ### C6. The machine runs out of memory during an install A profile-level `pnpm install` can grow to many GB on a large profile; with swap full, the kernel or earlyoom kills unrelated services. Check `free -m`, then: ```bash systemd-run --user --scope -p MemoryMax=3G dsh plugin --profile web add ```