Skip to content

Image tool: opaque "Failed to optimize image" when sharp is not installed #73148

@azgardtek

Description

@azgardtek

Summary

The image tool fails with the opaque error Failed to optimize image on every image in environments where the optional sharp package is not installed. The vision pipeline has no fallback and no clear indication that a missing native dependency is the cause.

Environment

  • OpenClaw: 2026.4.25 (aa36ee6)
  • Node: v22.22.2
  • OS: Ubuntu 24.04.4 LTS (x86_64)
  • Install: Linux VPS, OpenClaw installed globally to /usr/lib/node_modules/openclaw/

Reproduction

  1. Install OpenClaw on a fresh Linux host where sharp is not in node_modules (it is listed in OpenClaw's package.json onlyBuiltDependencies array but is not in dependencies / optionalDependencies, so it can be skipped during global install).
  2. Send any image to the agent (Discord attachment, file path, etc.).
  3. Call the image tool against the saved path:
    image({ image: "/path/to/any.jpg", prompt: "..." })
    
  4. Observe the response:
    { "status": "error", "tool": "image", "error": "Failed to optimize image" }

This happens regardless of input format (JPEG, PNG, WebP), size, dimensions, or EXIF orientation.

Root cause

/usr/lib/node_modules/openclaw/dist/extensions/media-understanding-core/image-ops.js does a dynamic import("sharp") at runtime. When the package isn't installed, every call to resizeToJpeg throws.

/usr/lib/node_modules/openclaw/dist/web-media-DaFqOHhS.js's optimizeImageToJpeg function tries 25 size×quality combinations (5 sides × 5 qualities) and swallows every per-attempt exception with try {} catch {}. After all 25 fail, it throws the generic Failed to optimize image — losing the underlying "sharp not found" cause entirely.

So the user-facing failure is one opaque message regardless of:

  • Sharp being missing (this case)
  • An actual image-corruption issue
  • An actual size/quality budget that nothing fits in

Suggested fix

Either or both:

1. Make sharp a hard dependency. It's clearly required for image attachment processing on non-macOS hosts (the only fallback is sips, which is macOS-only). Listing it in onlyBuiltDependencies without listing it in dependencies is what allows it to be skipped on Linux installs.

2. Surface the underlying error. In optimizeImageToJpeg, capture the first/last per-attempt exception and include it in the thrown message:

let lastErr = null;
for (...) try { ... } catch (e) { lastErr = e; }
...
throw new Error("Failed to optimize image" + (lastErr ? `: ${lastErr.message}` : ""), { cause: lastErr });

That alone would have made this a 30-second diagnosis instead of an hour.

A clearer message like "Failed to optimize image: Cannot find package 'sharp'" would immediately point the operator at the fix.

Workaround

sudo npm install --prefix /usr/lib/node_modules/openclaw sharp --no-save

(Adds 369 packages including libvips bindings, ~80MB.) After install, the image tool works for all formats. The fix survives until the next OpenClaw upgrade.

Impact

Any Linux deployment of OpenClaw where the install path skips optional native deps has a silently broken vision pipeline. Operators see image tool calls fail and have no clear path to diagnosis without reading the OpenClaw bundled JS.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions