dagger/dagger · error

%q is not a directory

Error message

%q is not a directory

What it means

newWorkdir validates that the resolved workdir root (from --workdir or cwd) is an existing directory before initializing the interactive shell's filesystem view. If os.Stat succeeds but the target is a regular file (or other non-directory), Dagger returns this error instead of starting the shell. It guards the shell against operating on paths it cannot traverse as a directory tree.

Source

Thrown at internal/cmd/dagger/shell_fs.go:433

		h.mu.RLock()
		context = h.wd.Context
		digest = h.wd.Module
		h.mu.RUnlock()
	}

	// initial context, without a loaded module (core API only)
	if context == nil {
		// a few quick checks first
		root, err := pathutil.Abs(subpath)
		if err != nil {
			return nil, err
		}
		info, err := os.Stat(root)
		if err != nil {
			return nil, err
		}
		if !info.IsDir() {
			return nil, fmt.Errorf("%q is not a directory", root)
		}

		if !h.noModule {
			// ask API where the context dir is (.git)
			ctx, span := Tracer().Start(ctx, "looking for context directory", telemetry.Internal())
			defer telemetry.EndWithCause(span, &rerr)

			src := h.dag.ModuleSource(root, dagger.ModuleSourceOpts{
				DisableFindUp:  true,
				AllowNotExists: true,
			})
			root, err = src.LocalContextDirectoryPath(ctx)
			if err != nil {
				return nil, err
			}
			subpath, err = src.SourceRootSubpath(ctx)
			if err != nil {
				return nil, err

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Pass a directory path to --workdir (or run from a directory), not a file
  2. Verify with 'ls -la <path>' or 'os.Stat' that the target is a directory
  3. If a symlink is involved, confirm it resolves to a directory
  4. Update the calling script (Initialize/ChangeDir input) to strip the filename component

Example fix

// before
dagger --workdir ./config.yaml

// after
dagger --workdir .
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(root)
if err != nil { return err }
if !info.IsDir() { return fmt.Errorf("%q is not a directory", root) }
// only then: dagger --workdir root

Try / catch

if err := runDaggerShell(); err != nil {
  if strings.Contains(err.Error(), "is not a directory") {
    // fix workdir path and retry
  }
}

Prevention

When it happens

Trigger: Running 'dagger' shell / 'dagger terminal'-style init with --workdir pointing to a file (e.g. --workdir ./dagger.config.ts), or when the cwd path resolves to a file; also reached via ChangeDir into a non-directory path.

Common situations: Typo where a filename is passed instead of its parent directory; a symlink resolving to a file; scripts that compute the workdir path and accidentally append a filename; workdir deleted and replaced by a file.

Related errors


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