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

  1. Inspect the wrapped inner error to see the actual load failure cause.
  2. Re-obtain the From workspace ID from a live query in the same session rather than reusing a stored one.
  3. Validate the ID string before passing it (not truncated, correct type — Workspace not Directory).
  4. 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

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


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/0286c568c2152ca9. Report an issue: GitHub.