{"id":"7e261856d7c9947a","repo":"docker/cli","slug":"context-must-be-a-directory","errorCode":null,"errorMessage":"context must be a directory","messagePattern":"context must be a directory","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/command/plugin/create.go","lineNumber":55,"sourceCode":"\terr = json.NewDecoder(dt).Decode(&m)\n\t_ = dt.Close()\n\n\treturn err\n}\n\n// validateContextDir validates the given dir and returns its absolute path on success.\nfunc validateContextDir(contextDir string) (string, error) {\n\tabsContextDir, err := filepath.Abs(contextDir)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tstat, err := os.Lstat(absContextDir)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tif !stat.IsDir() {\n\t\treturn \"\", errors.New(\"context must be a directory\")\n\t}\n\n\treturn absContextDir, nil\n}\n\ntype pluginCreateOptions struct {\n\trepoName string\n\tcontext  string\n\tcompress bool\n}\n\nfunc newCreateCommand(dockerCLI command.Cli) *cobra.Command {\n\toptions := pluginCreateOptions{}\n\n\tcmd := &cobra.Command{\n\t\tUse:   \"create [OPTIONS] PLUGIN PLUGIN-DATA-DIR\",\n\t\tShort: \"Create a plugin from a rootfs and configuration. Plugin data directory must contain config.json and rootfs directory.\",\n\t\tArgs:  cli.RequiresMinArgs(2),","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/docker/cli/blob/e9452d6e785f6e365712b9d71bd7517591773c86/cli/command/plugin/create.go#L37-L73","documentation":"Raised by validateContextDir during `docker plugin create` when the given plugin context path exists (Lstat succeeds) but is not a directory. A plugin build context must be a directory containing config.json and a rootfs; a file, symlink to a file, or tarball path is rejected.","triggerScenarios":"`docker plugin create myplugin ./path` where ./path is a regular file (e.g. a .tar.gz or the config.json itself) or a symlink whose Lstat target is not a directory.","commonSituations":"Pointing the command at a plugin tarball instead of the unpacked directory; passing config.json directly instead of its parent directory; typo resolving to a file.","solutions":["Pass the directory containing config.json and rootfs/: `docker plugin create myplugin ./plugin-dir`","If you have a tarball, extract it first (tar -xf plugin.tar.gz -C plugin-dir) and pass the directory","Check the path with `ls -ld <path>` to confirm it is a directory"],"exampleFix":"# before\ndocker plugin create myplugin ./plugin.tar.gz\n# after\nmkdir plugin-dir && tar -xzf plugin.tar.gz -C plugin-dir\ndocker plugin create myplugin ./plugin-dir","handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":["docker","plugin","build-context","filesystem"],"analyzedSha":"e9452d6e785f6e365712b9d71bd7517591773c86","analyzedAt":"2026-08-01T07:09:22.474Z","schemaVersion":2}