Skip to main content
When an operation fails, the engine returns a JSON object with success: false instead of a normal JobResult. The outputs and metadata fields are absent; an error field is present with a human-readable description of what went wrong.

Error response structure

success
boolean
required
Always false for error responses.
operation
string
required
The name of the operation that failed, e.g. "resize" or "crop". Use this to correlate errors in streaming sessions where multiple jobs may be in flight.
error
string
required
Human-readable description of the error.

Example

{
  "success": false,
  "operation": "resize",
  "error": "Input file not found: missing.png"
}

Common errors

Error messageCause
Input file not foundThe path in input or inputs does not exist or is not readable.
Invalid image formatThe file exists but cannot be decoded — unsupported format or corrupted data.
width is requiredA resize or similar operation was submitted without a widths array or scale_percent.
Must specify either 'rect' or 'gravity'A crop job did not include either a manual rectangle or a smart crop mode.
Invalid rotation angleThe angle field for a rotate job is not one of 0, 90, 180, or 270.
Opacity must be between 0.0 and 1.0The opacity value on a watermark job is outside the valid range.
Output path requiredAn operation that writes a single file (e.g. crop, rotate, watermark) was sent without an output field.
At least one width must be specifiedThe widths array on a resize or srcset job was empty.

Error handling in Go

The Go client distinguishes between two categories of failure:
  1. Transport / spawn errors — the err return value from a client method is non-nil. The Rust process could not start, timed out, or crashed before writing a response.
  2. Operation errorserr is nil but result.Success is false. The engine ran successfully and returned a structured error describing what went wrong with the job.
You must check both independently.
result, err := client.Resize(ctx, "photo.jpg", "dist", []uint32{320, 640})
if err != nil {
    // Transport or process-level failure.
    // The engine did not produce a response.
    log.Printf("engine error: %v", err)
    return
}

if !result.Success {
    // Operation-level failure.
    // result.Operation identifies which operation failed.
    // result.Error (if using raw JSON) contains the message.
    log.Printf("operation %q failed after %dms", result.Operation, result.ElapsedMs)
    return
}

// Success path.
for _, out := range result.Outputs {
    log.Printf("wrote %s (%d bytes)", out.Path, out.SizeBytes)
}
For the StreamClient, the pattern is identical:
sc, err := dpf.NewStreamClient("./bin/dpf")
if err != nil {
    log.Fatal(err)
}
defer sc.Close()

result, err := sc.Execute(&dpf.ResizeJob{
    Operation: "resize",
    Input:     "photo.jpg",
    OutputDir: "dist",
    Widths:    []uint32{320, 640},
})
if err != nil {
    log.Printf("stream error: %v", err)
    return
}

if !result.Success {
    log.Printf("operation %q failed", result.Operation)
    return
}

log.Printf("success in %dms: %+v", result.ElapsedMs, result.Outputs)
Log both err and result details when troubleshooting. The err value contains low-level process information (exit code, stderr output), while result.Operation and the raw error field from the JSON tell you exactly which job failed and why. Capturing both is essential for diagnosing issues in production.

Timeout configuration

Operations that process large files (video transcode, batch jobs) can take longer than the default 30-second timeout. Adjust it before sending the job:
client := dpf.NewClient("./bin/dpf")

// Default: 30 seconds — suitable for most image operations.
client.SetTimeout(30 * time.Second)

// For video processing.
client.SetTimeout(5 * time.Minute)

// For quick image operations.
client.SetTimeout(10 * time.Second)
A timeout results in a non-nil err return value with a context deadline message; result will be nil.

Build docs developers (and LLMs) love