basecamp/kamal · error · ArgumentError

Invalid builder configuration: the `docker` driver does not

Error message

Invalid builder configuration: the `docker` driver does not not support caching

What it means

Kamal::Configuration::Builder#valid? raises this ArgumentError when `driver: docker` is combined with caching (cached? true, i.e. a cache `type:` or `image:` configured under builder). Cache export/import is a buildx/docker-container feature; the plain docker driver builds directly in the daemon and cannot attach a cache backend, so the configuration is rejected up front.

Source

Thrown at lib/kamal/configuration/builder.rb:163

  def build_directory
    @build_directory ||=
      if git_clone?
        File.join clone_directory, repo_basename, repo_relative_pwd
      else
        "."
      end
  end

  def docker_driver?
    driver == "docker"
  end

  private
    def valid?
      if docker_driver?
        raise ArgumentError, "Invalid builder configuration: the `docker` driver does not not support remote builders" if remote
        raise ArgumentError, "Invalid builder configuration: the `docker` driver does not not support caching" if cached?
        raise ArgumentError, "Invalid builder configuration: the `docker` driver does not not support multiple arches" if arches.many?
      end

      if @options["cache"] && @options["cache"]["type"]
        raise ArgumentError, "Invalid cache type: #{@options["cache"]["type"]}" unless [ "gha", "registry" ].include?(@options["cache"]["type"])
      end
    end

    def cache_image
      builder_config["cache"]&.fetch("image", nil) || "#{image}-build-cache"
    end

    def cache_image_ref
      [ server, cache_image ].compact.join("/")
    end

    def cache_options
      builder_config["cache"]&.fetch("options", nil)

View on GitHub (pinned to eee0083b38)

Solutions

  1. Remove the `cache:` block (or set no cache type) when using `driver: docker`.
  2. Or keep caching and use the default buildx/docker-container driver, which supports `cache: { type: gha|registry }`.
  3. Check the fully merged config with `kamal config` when base and environment overrides both touch builder.

Example fix

# config/deploy.yml — before
builder:
  driver: docker
  cache:
    type: gha

# after
builder:
  cache:
    type: gha
Defensive patterns

Strategy: validation

Validate before calling

def builder_driver_cache_compatible?(raw)
  b = raw["builder"] || {}
  !(b["driver"] == "docker" && (b.dig("cache", "type") || b.dig("cache", "image")))
end

Try / catch

begin
  Kamal::Configuration.new(create_config_files: false)
rescue ArgumentError, Kamal::ConfigurationError => e
  abort "#{e.message} — caching needs the buildx driver"
end

Prevention

When it happens

Trigger: `builder: { driver: docker, cache: { type: gha } }` in config/deploy.yml; inheriting a cache block from a shared base config while an environment override switches the driver to docker; enabling caching for CI speed and later switching drivers without pruning cache keys.

Common situations: Layered kamal configs merging incompatible builder keys; performance tuning carried over from buildx setups; docs and tutorials mixing driver and cache examples.

Related errors


AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21). Data as JSON: /api/errors/8fc02a0c3c982d3e. Report an issue: GitHub.