{"record":{"id":"8f0038c9bc971899","repo":"docker/compose","slug":"cannot-specify-deprecated-workdir-and-proje","errorCode":null,"errorMessage":"cannot specify DEPRECATED \"--workdir\" and \"--project-directory\". Please use only \"--project-directory\" instead","messagePattern":"cannot specify DEPRECATED \"--workdir\" and \"--project-directory\"\\. Please use only \"--project-directory\" instead","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/compose/compose.go","lineNumber":520,"sourceCode":"\n\t\t\tswitch ansi {\n\t\t\tcase \"never\":\n\t\t\t\tdisplay.Mode = display.ModePlain\n\t\t\tcase \"always\":\n\t\t\t\tdisplay.Mode = display.ModeTTY\n\t\t\t}\n\n\t\t\tdetached, _ := cmd.Flags().GetBool(\"detach\")\n\t\t\tep, err := selectEventProcessor(dockerCli, opts.Progress, ansi, detached)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tbackendOptions.Add(compose.WithEventProcessor(ep))\n\n\t\t\t// (4) options validation / normalization\n\t\t\tif opts.WorkDir != \"\" {\n\t\t\t\tif opts.ProjectDir != \"\" {\n\t\t\t\t\treturn errors.New(`cannot specify DEPRECATED \"--workdir\" and \"--project-directory\". Please use only \"--project-directory\" instead`)\n\t\t\t\t}\n\t\t\t\topts.ProjectDir = opts.WorkDir\n\t\t\t\tfmt.Fprint(os.Stderr, aec.Apply(\"option '--workdir' is DEPRECATED at root level! Please use '--project-directory' instead.\\n\", aec.RedF))\n\t\t\t}\n\t\t\tfor i, file := range opts.EnvFiles {\n\t\t\t\tfile = composepaths.ExpandUser(file)\n\t\t\t\tif !filepath.IsAbs(file) {\n\t\t\t\t\tfile, err := filepath.Abs(file)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t\topts.EnvFiles[i] = file\n\t\t\t\t} else {\n\t\t\t\t\topts.EnvFiles[i] = file\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcomposeCmd := cmd","sourceCodeStart":502,"sourceCodeEnd":538,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/cmd/compose/compose.go#L502-L538","documentation":"The hidden root flag --workdir is deprecated in favor of --project-directory, and the two cannot be combined. During option normalization in cmd/compose/compose.go, if opts.WorkDir is non-empty while opts.ProjectDir is also set, the command fails immediately. --workdir alone still works: its value is copied into ProjectDir and a red deprecation notice is printed to stderr.","triggerScenarios":"Any docker compose invocation that passes both flags, e.g. `docker compose --workdir /app --project-directory /other up`, or a wrapper/alias that always injects --project-directory while the user adds --workdir.","commonSituations":"Scripts or Makefiles dating from Compose v1 (which used --workdir) that were partially migrated to v2 syntax; tools like IDE run configurations that append --project-directory automatically while the user adds --workdir manually.","solutions":["Replace --workdir <path> with --project-directory <path> and keep a single occurrence of the flag.","Check shell aliases and CI templates for leftover --workdir usage and update them.","Alternatively use the COMPOSE_PROJECT_DIR environment variable if supported by your workflow, but prefer the explicit flag."],"exampleFix":"# before\ndocker compose --workdir /srv/app --project-directory /srv/app up\n\n# after\ndocker compose --project-directory /srv/app up","handlingStrategy":"validation","validationCode":"# reject command lines mixing both flags\nif printf '%s\\n' \"$@\" | grep -q -- '--workdir' && printf '%s\\n' \"$@\" | grep -q -- '--project-directory'; then\n  echo \"--workdir is deprecated; keep only --project-directory\" >&2\n  exit 1\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Migrate all v1-era scripts from --workdir to --project-directory once, centrally.","Lint compose invocations in CI (grep for --workdir) to catch regressions."],"tags":["cli","flags","deprecated","project-directory"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}