dagger/dagger · error
workspace working directory %q must be a relative path withi
Error message
workspace working directory %q must be a relative path within the workspace root
What it means
Workspace.withWorkdir validates that the requested working directory stays inside the workspace root. After cleaning the path, absolute paths, the value "..", or any path escaping via a "../" prefix are rejected with this explicit validation message. It is a deliberate public-schema guard: the working directory must remain a relative path within the workspace.
Source
Thrown at core/schema/workspace.go:1814
}
func (s *workspaceSchema) withWorkdir(
ctx context.Context,
parent dagql.ObjectResult[*core.Workspace],
args struct {
Path string
},
) (dagql.ObjectResult[*core.Workspace], error) {
srv, err := core.CurrentDagqlServer(ctx)
if err != nil {
return dagql.ObjectResult[*core.Workspace]{}, err
}
// Public schema surface: keep the working directory inside the workspace root.
// cleanWorkspaceRelPath is only filepath.Clean, so reject absolute paths and
// anything escaping via "..".
cwd := cleanWorkspaceRelPath(args.Path)
if filepath.IsAbs(args.Path) || cwd == ".." || strings.HasPrefix(cwd, ".."+string(filepath.Separator)) {
return dagql.ObjectResult[*core.Workspace]{}, fmt.Errorf("workspace working directory %q must be a relative path within the workspace root", args.Path)
}
ws := parent.Self().Clone()
ws.Cwd = cwd
return dagql.NewObjectResultForCurrentCall(ctx, srv, ws)
}
type workspaceWithMountedDirectoryArgs struct {
Path string
Source core.DirectoryID
}
func (s *workspaceSchema) withMountedDirectory(
ctx context.Context,
parent dagql.ObjectResult[*core.Workspace],
args workspaceWithMountedDirectoryArgs,
) (dagql.ObjectResult[*core.Workspace], error) {
return withMountedSource(ctx, parent, args.Path, args.Source, "withDirectory")
}View on GitHub (pinned to 82ba2681db)
Solutions
- Pass a workspace-relative path (e.g. "src/app" instead of "/src/app").
- Strip or convert any absolute prefix before calling withWorkdir.
- Reject or normalize paths containing ".." before invoking the API.
- Use filepath.ToSlash/clean on the input and confirm it does not start with the separator or "..".
Example fix
// before
await ws.withWorkdir("/src/app")
// error: workspace working directory "/src/app" must be a relative path...
// after
await ws.withWorkdir("src/app") Defensive patterns
Strategy: validation
Validate before calling
function assertWorkspaceRelPath(p) {
const clean = p.replace(/\\/g, "/").replace(/(^|\/)\.\.?($|\/)/g, "/")
.split("/").filter(Boolean).join("/")
if (!p || p.startsWith("/") || p === ".." || p.startsWith("../") || clean.startsWith("..")) {
throw new Error(`workdir must be relative within workspace: ${p}`)
}
return clean || "."
} Type guard
const isSafeWorkdir = (p) => typeof p === 'string' && p.length > 0 && !p.startsWith('/') && p !== '..' && !p.startsWith('../'); Try / catch
try {
ws = await ws.withWorkdir(path)
} catch (e) {
if (String(e.message).includes("must be a relative path within the workspace root")) {
// normalize path to workspace-relative and retry
}
throw e
} Prevention
- Always pass workspace-relative paths to withWorkdir
- Strip host-specific absolute prefixes before the call
- Resolve and reject ".." segments in caller-supplied paths
When it happens
Trigger: Calling Workspace.withWorkdir with an absolute path (e.g. "/src" or "C:\\src"), with "..", or with a path like "../outside".
Common situations: Reusing workdir values meant for a shell/container (absolute paths) instead of workspace-relative ones; computing paths by joining with the host cwd; path traversal attempts to read outside the workspace.
Related errors
- cannot mount over the workspace root
- workspace %q: local path is not a directory
- path %s is a file, not a directory
- file name %q must not contain a directory
- object %q field %q: Workspace cannot be stored as a field on
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/1f8fc3e4d1e582a8.
Report an issue: GitHub.