# Vision Auxiliary Diagnosis (2026-08-13)

Symptom: `vision_analyze` fails with `Request timed out` after exactly 2× the
configured timeout (120s×2 = ~242s), or previously `HTTP 404: Model not exist`.
Not a Feishu-channel issue and not the main chat model — vision_analyze is a
local Hermes call to an auxiliary vision model; the gateway only carries text.

## Diagnostic ladder (worked end-to-end)
1. `grep -i vision ~/.hermes/logs/errors.log | tail` — look for
   `Vision provider X unavailable, falling back to auto` (configured provider
   has no key) and the actual wire error.
2. Check `auxiliary.vision` in config.yaml. If provider has no API key
   (e.g. openrouter with OPENROUTER_API_KEY commented out), the fallback
   inherits the OpenRouter-style model name (`qwen/qwen-3-vl`) and passes it
   verbatim to whatever backend auto resolves to → 404 Model not exist.
3. Point auxiliary.vision at a working endpoint (here: same custom endpoint as
   the main model, model=qwen3.8-max — it natively accepts image input; test
   with a >10px image, the endpoint rejects 1×1 test images with a size error,
   which is PROOF image input works).
4. If calls now hang to timeout but curl/OpenAI-SDK calls with the same
   image/key succeed in seconds: the culprit is Hermes' vision prompt
   ("Fully describe and explain everything about this image") hitting a
   REASONING model — measured 19,437 reasoning chars / 131s on a 9-panel
   chart, just past the 120s timeout → retry → timeout again → fail.

## Fix
```bash
hermes config set auxiliary.vision.provider custom
hermes config set auxiliary.vision.model qwen3.8-max
hermes config set auxiliary.vision.base_url <endpoint>/compatible-mode/v1
hermes config set auxiliary.vision.api_key '${ENV_KEY_VAR}'
hermes config set auxiliary.vision.extra_body.enable_thinking false
hermes config set auxiliary.vision.timeout 300
```
Then `/restart` the gateway — auxiliary config is read at startup; stale
in-memory config keeps timing out until restart. Result: 131s → 4.7s.

## Notes
- `extra_body` under auxiliary.<task> is natively supported
  (`_get_task_extra_body` reads the nested dict and merges it into the call).
- `hermes config set` warns "not a recognized config key" for nested
  extra_body keys but saves anyway — the warning is harmless here.
- Reasoning models are wasteful for perception tasks (describe/locate/measure);
  disable thinking only for the vision task, not the main conversation.
- Verify with a real image, not a 1×1 px probe (endpoint min-size rule).

## New symptom 2026-08-18: `unknown variant \`image_url\`` — PNG→JPEG works
- Error: `400 ... messages[0]: unknown variant \`image_url\`, expected \`text\``
  — endpoint rejects the OpenAI-style image_url content block for THIS image.
  Occurred with 2190×1493 PNG and with a 1095×746 resized PNG (so size alone
  was not the trigger).
- **Workaround that succeeded: convert to a ~1000px JPEG (quality≈82) and
  retry** — same endpoint, same config, same question → analysis returned.
- Ladder: try JPEG conversion before touching auxiliary.vision config; only if
  JPEG also fails, escalate to the config diagnosis above. (Root cause still
  unconfirmed — possibly endpoint-side content-type handling for large PNGs;
  the JPEG path is a reliable bypass as of this date.)
