{"record":{"id":"90dacd8b5df3d445","repo":"apple/pkl","slug":"cannot-download-packages-because-no-cache-director","errorCode":null,"errorMessage":"Cannot download packages because no cache directory is specified.","messagePattern":"Cannot download packages because no cache directory is specified\\.","errorType":"exception","errorClass":"CliException","httpStatus":null,"severity":"error","filePath":"pkl-cli/src/main/kotlin/org/pkl/cli/CliPackageDownloader.kt","lineNumber":32,"sourceCode":" * limitations under the License.\n */\npackage org.pkl.cli\n\nimport org.pkl.commons.cli.CliBaseOptions\nimport org.pkl.commons.cli.CliCommand\nimport org.pkl.commons.cli.CliException\nimport org.pkl.core.packages.PackageResolver\nimport org.pkl.core.packages.PackageUri\n\nclass CliPackageDownloader(\n  baseOptions: CliBaseOptions,\n  private val packageUris: List<PackageUri>,\n  private val noTransitive: Boolean,\n) : CliCommand(baseOptions) {\n\n  override fun doRun() {\n    if (moduleCacheDir == null) {\n      throw CliException(\"Cannot download packages because no cache directory is specified.\")\n    }\n    val packageResolver = PackageResolver.getInstance(securityManager, httpClient, moduleCacheDir)\n    val errors = mutableMapOf<PackageUri, Throwable>()\n    for (pkg in packageUris) {\n      try {\n        packageResolver.downloadPackage(pkg, pkg.checksums, noTransitive)\n      } catch (e: Throwable) {\n        errors[pkg] = e\n      }\n    }\n    when (errors.size) {\n      0 -> return\n      1 ->\n        throw CliException(\n          errors.values.single().message\n            ?: (\"An unexpected error occurred: \" + errors.values.single())\n        )\n      else ->","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-cli/src/main/kotlin/org/pkl/cli/CliPackageDownloader.kt#L14-L50","documentation":"`pkl package download` requires a module cache directory to store downloaded packages; when none is configured (no `--cache-dir`, no `PKL_CACHE_DIR`, etc.) the downloader throws immediately in doRun before resolving anything.","triggerScenarios":"Running `pkl package download ...` in an environment where the cache directory is null — e.g. a minimal container or CI job without `PKL_CACHE_DIR` set and without a user cache dir.","commonSituations":"Docker images run with a stripped HOME; CI runners that unset XDG env vars; hermetic test environments that intentionally disable caching.","solutions":["Pass `--cache-dir /path/to/cache` on the command line.","Set the `PKL_CACHE_DIR` environment variable to a writable directory.","Ensure HOME (or XDG_CACHE_HOME) is set so the default cache location can be derived."],"exampleFix":"# before\npkl package download package://example.com/foo@1.0.0\n# after\nPKL_CACHE_DIR=$HOME/.pkl/cache pkl package download package://example.com/foo@1.0.0","handlingStrategy":"validation","validationCode":"if (System.getenv(\"PKL_CACHE_DIR\") == null && !Files.isDirectory(Path.of(System.getProperty(\"user.home\"), \".pkl/cache\"))) {\n  throw IllegalStateException(\"no Pkl cache directory configured; set PKL_CACHE_DIR\")\n}","typeGuard":null,"tryCatchPattern":"try {\n  pklCli.runPackageDownload(args)\n} catch (e: CliException) {\n  if (\"no cache directory\" in (e.message ?: \"\")) {\n    exec(\"pkl package download --cache-dir ${cacheDir()} ...\")\n  } else throw e\n}","preventionTips":["Set PKL_CACHE_DIR in Docker images and CI environments.","Keep HOME/XDG_CACHE_HOME set when running the CLI.","Pass --cache-dir explicitly in hermetic builds."],"tags":["cli","package-download","cache"],"backgroundTag":"missing-env-var","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}