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

  1. Pass a workspace-relative path (e.g. "src/app" instead of "/src/app").
  2. Strip or convert any absolute prefix before calling withWorkdir.
  3. Reject or normalize paths containing ".." before invoking the API.
  4. 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

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


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