dagger/dagger · error
absolute module ref %q requires a local workspace source
Error message
absolute module ref %q requires a local workspace source
What it means
Thrown by resolveWorkspaceClientModuleRef in core/schema/workspace_client.go:225 when a client's module ref is an absolute filesystem path but the workspace has no local host source (LocalSourceHostPath fails). Absolute module refs can only be rewritten relative to the workspace root when the workspace is backed by a real local directory on the host.
Source
Thrown at core/schema/workspace_client.go:225
return resolved, nil
}
// resolveWorkspaceClientModuleRef normalizes a client's module ref into the two
// forms it is needed in: loadRef, workspace-root-relative, is what module
// loading reads from, while configRef is how the entry is spelled in the
// dagger.toml at configDir. A canonical ref has no anchor, so it is both.
func resolveWorkspaceClientModuleRef(ws *core.Workspace, ref, configDir string) (loadRef string, configRef string, _ error) {
if !workspace.IsLocalRef(ref, "") {
return ref, ref, nil
}
// A local ref may be spelled with Windows separators; every path below this
// point is addressed on the engine, where filepath treats a backslash as an
// ordinary character.
cleaned := filepath.Clean(strings.ReplaceAll(ref, `\`, "/"))
if filepath.IsAbs(cleaned) {
hostRoot, ok := ws.LocalSourceHostPath()
if !ok {
return "", "", fmt.Errorf("absolute module ref %q requires a local workspace source", ref)
}
rel, err := filepath.Rel(hostRoot, cleaned)
if err != nil {
return "", "", fmt.Errorf("compute workspace-relative module path: %w", err)
}
cleaned = rel
}
if cleaned == "." || cleaned == "" {
cleaned = "."
}
if cleaned == ".." || strings.HasPrefix(cleaned, ".."+string(filepath.Separator)) {
return "", "", fmt.Errorf("module ref %q must not escape the workspace root", ref)
}
loadRef = filepath.ToSlash(cleaned)
configRef, err := workspace.SDKManagedPathFor(configDir, loadRef)
if err != nil {
return "", "", err
}View on GitHub (pinned to 82ba2681db)
Solutions
- Use a module ref relative to the workspace root or your cwd instead of an absolute host path
- Run the command from a workspace with a local host source directory (a checked-out workspace on the host)
- If the module is remote, use its git ref form instead of a local absolute path
Example fix
// before dagger workspace client init --path=./client --sdk=go --module=/home/me/proj/shared // after dagger workspace client init --path=./client --sdk=go --module=./shared
Defensive patterns
Strategy: validation
Validate before calling
// shell: only pass absolute module refs when working from a local checkout
[ -d .git ] || [ -f dagger.toml ] || { echo 'use a workspace-relative module ref'; exit 1; } Type guard
func isRelativeModuleRef(ref string) bool {
return ref != "" && !filepath.IsAbs(filepath.Clean(strings.ReplaceAll(ref, "\\", "/")))
} Prevention
- Use workspace-relative or git module refs instead of absolute host paths
- Only rely on absolute refs when the workspace is a real local directory on the host
- Avoid absolute paths in scripted/CI invocations
When it happens
Trigger: Passing an absolute module ref (e.g. /home/me/proj/shared, or a Windows path with backslashes) to dagger workspace client init / currentModuleAsSDKClientModuleSource while the workspace source is remote (e.g. a git-sourced or in-container workspace without a local host path).
Common situations: Running against a workspace whose source lives in a container/remote context while passing a host-absolute path; using an absolute path out of habit in CI where the workspace is not host-mounted.
Related errors
- module ref %q must not escape the workspace root
- cannot create directory outside parent: %s
- client path %q must not escape the workspace root
- client path must point to a directory below the workspace ro
- compute workspace-relative module path: %w
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/1e3f21538a845005.
Report an issue: GitHub.