dagger/dagger · error
load comparison workspace: %w
Error message
load comparison workspace: %w
What it means
Workspace.changes supports diffing against a second workspace passed via the From argument. Before comparing, the From workspace ID is loaded back into an object (args.From.Value.Load). Any failure resolving that ID is wrapped as "load comparison workspace: %w", so the underlying cause (invalid/stale ID, missing object, engine error) surfaces with this context prefix.
Source
Thrown at core/schema/workspace.go:1938
} else {
empty, err := core.NewEmptyChangeset(ctx)
if err != nil {
return inst, err
}
changes, err = dagql.NewObjectResultForCurrentCall(ctx, srv, empty)
if err != nil {
return inst, err
}
}
if callerPastChangesetCwdCutover(ctx) {
return reRootChangesetToCwd(ctx, changes, parent.Self().Cwd)
}
return changes, nil
}
from, err := args.From.Value.Load(ctx, srv)
if err != nil {
return inst, fmt.Errorf("load comparison workspace: %w", err)
}
changes, err := s.workspaceChangesBetween(ctx, from, parent)
if err != nil {
return inst, err
}
if callerPastChangesetCwdCutover(ctx) {
return reRootChangesetToCwd(ctx, changes, parent.Self().Cwd)
}
return changes, nil
}
// workspaceChangesBetween compares two workspace values without materializing
// an entire client-local workspace. Host-backed workspaces are reconstructed
// over a sparse host view containing only paths touched by either side; all
// other workspace kinds already have full in-engine roots.
func (s *workspaceSchema) workspaceChangesBetween(
ctx context.Context,View on GitHub (pinned to 82ba2681db)
Solutions
- Inspect the wrapped inner error to see the actual load failure cause.
- Re-obtain the From workspace ID from a live query in the same session rather than reusing a stored one.
- Validate the ID string before passing it (not truncated, correct type — Workspace not Directory).
- Retry if the inner cause was a transient engine error.
Example fix
// before
changes := ws.Changes(ctx, dagger.WorkspaceChangesOpts{From: oldSavedID}) // may fail to load
// after
fromWs := client.Workspace().WithDirectory(...) // recreate From workspace in-session
changes := ws.Changes(ctx, dagger.WorkspaceChangesOpts{From: fromWs.ID()}) Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the ID is a non-empty, plausible dagql ID before calling changes
if fromID == "" || !strings.Contains(fromID, ":") {
return errors.New("invalid workspace ID for From argument")
} Try / catch
changes, err := ws.Changes(ctx, dagger.WorkspaceChangesOpts{From: fromID})
if err != nil {
if strings.Contains(err.Error(), "load comparison workspace") {
from := client.Host().Workspace(".") // recreate From in this session
changes, err = ws.Changes(ctx, dagger.WorkspaceChangesOpts{From: from.ID()})
}
if err != nil {
return err
}
} Prevention
- Never persist workspace IDs across sessions; recreate workspaces per run.
- Pass live Workspace objects/IDs obtained in the same client session.
- Validate ID strings for truncation or type mix-ups (Workspace vs Directory).
When it happens
Trigger: Calling workspace.changes(from: <workspaceID>) where the ID cannot be loaded: it references a deleted/non-existent Workspace, is malformed, or the engine errors while materializing the referenced workspace.
Common situations: Reusing a saved workspace ID from a previous session or different pipeline run; truncating or mis-concatenating the ID string; using an ID from another client/query context.
Related errors
- get bound workspace ID: %w
- invalid enum member %q for %s
- verify skipped modules: %w
- read workspace root: %w
- default value for %q: %w
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/0286c568c2152ca9.
Report an issue: GitHub.