dagger/dagger · error
workspace client metadata: %w
Error message
workspace client metadata: %w
What it means
This error wraps a failure from query.SpecificClientMetadata when workspaceClientContext tries to switch the context to the Workspace's owning client. Only workspaces with a non-empty ClientID take this path; synthetic/value workspaces return early. If the owning client's metadata cannot be looked up (client no longer registered in the engine's client registry, e.g. the owning session disconnected), the lookup fails and this wrapped error is returned to WorkspaceServedContext / WorkspaceServedSchema.
Source
Thrown at core/workspace_context.go:160
// client-scoped resolvers — CurrentServedDeps, EnsureWorkspaceModules — resolve
// against the workspace's own served modules rather than whichever client is
// currently executing. Synthetic/value workspaces have no owning client, so ctx
// is returned unchanged and resolution falls back to the current client.
//
// This mirrors core/schema's withWorkspaceClientContext, reimplemented here so
// the LLM's schema derivation ([WorkspaceServedSchema]) needs no core→schema
// import.
func workspaceClientContext(ctx context.Context, ws *Workspace) (context.Context, error) {
if ws.ClientID == "" {
return ctx, nil
}
query, err := CurrentQuery(ctx)
if err != nil {
return nil, err
}
clientMetadata, err := query.SpecificClientMetadata(ctx, ws.ClientID)
if err != nil {
return nil, fmt.Errorf("workspace client metadata: %w", err)
}
return engine.ContextWithClientMetadata(ctx, clientMetadata), nil
}
// WorkspaceServedSchema returns the stable served GraphQL schema for a
// Workspace. Pending overlays are resolved only by explicit agent
// recomposition; bound object tools retain the schema that defined them.
func WorkspaceServedSchema(ctx context.Context, ws dagql.ObjectResult[*Workspace]) (*dagql.Server, error) {
wsCtx, err := WorkspaceServedContext(ctx, ws)
if err != nil {
return nil, err
}
query, err := CurrentQuery(ctx)
if err != nil {
return nil, err
}
deps, err := query.CurrentServedDeps(wsCtx)
if err != nil {View on GitHub (pinned to 82ba2681db)
Solutions
- Re-obtain the Workspace in the current session (re-select currentWorkspace or rebuild it) instead of reusing a Workspace from a previous/foreign client.
- Ensure the owning client session stays alive for as long as the Workspace is used (don't let the parent call return before dependent tool/schema calls).
- If the workspace is synthetic/value-only, verify ClientID is empty so the client switch is skipped.
- Check the wrapped error for 'client not found' style messages to confirm the owning session ended; then rebind the workspace to the current client.
Example fix
// before: reusing a workspace captured from an earlier session
ws := savedWorkspaceFromPreviousSession
schema, err := core.WorkspaceServedSchema(ctx, ws)
// after: reload the workspace in the live session
var ws dagql.ObjectResult[*core.Workspace]
srv.Select(ctx, srv.Root(), &ws, dagql.Selector{Field: "currentWorkspace"})
schema, err := core.WorkspaceServedSchema(ctx, ws) Defensive patterns
Strategy: validation
Validate before calling
// only reuse a workspace whose owning client is still the live one
if ws.Self().ClientID != "" && ws.Self().ClientID != currentSessionClientID {
// reload the workspace in the current session before calling WorkspaceServedSchema
return errors.New("workspace belongs to a finished client session; reload it")
} Type guard
func workspaceOwnedByLiveClient(ws *core.Workspace, liveClientID string) bool {
return ws.ClientID == "" || ws.ClientID == liveClientID
} Try / catch
ctx, err := core.WorkspaceServedContext(ctx, ws)
if err != nil {
if strings.Contains(err.Error(), "workspace client metadata") {
// owning client gone: reload workspace in current session and retry once
}
return err
} Prevention
- Don't retain Workspace object results beyond their owning call/session lifetime.
- Reload workspaces from the live session instead of caching them across sessions.
- Keep the owning client session open while dependent schema/inspect calls run.
- Treat empty ClientID (synthetic workspaces) as safe to reuse anywhere.
When it happens
Trigger: Calling WorkspaceServedContext or WorkspaceServedSchema with a Workspace whose ClientID is set but whose owning client session is gone: the client that created the workspace disconnected/closed, the ClientID is stale (workspace persisted or passed across sessions), or the metadata store lookup errors.
Common situations: An LLM/agent tool (bound via withWorkspace) referencing a Workspace whose originating client call has already returned; replaying a workspace across a new dagger session; engine restart invalidating old client IDs; holding a Workspace object result longer than its owning call's lifetime.
Related errors
- failed to get client metadata: %w
- unknown type %q
- enum types must be named
- failed to find decl for object %s: %w
- failed to find decl for named type %s: %w
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/44f6183faa121a09.
Report an issue: GitHub.