basecamp/kamal · error · ArgumentError

Invalid cache type: #{@options["cache"]["type"]}

Error message

Invalid cache type: #{@options["cache"]["type"]}

What it means

Kamal::Configuration::Builder#valid? checks that when a cache type is configured (`builder.cache.type` present), it is one of exactly "gha" (GitHub Actions cache) or "registry" (cache image in the container registry). Any other string raises this ArgumentError with the offending value, since Kamal only knows how to wire those two buildx cache backends.

Source

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

      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)
    end

    def cache_from_config_for_gha
      individual_options = cache_options&.split(",") || []
      allowed_options = individual_options.select { |option| option =~ /^(url|url_v2|token|scope|timeout)=/ }

View on GitHub (pinned to eee0083b38)

Solutions

  1. Set `cache.type` to `gha` or `registry` exactly (lowercase).
  2. Choose gha when deploying from GitHub Actions; registry when an ordinary registry-backed cache fits all environments.
  3. If the value is ENV-driven, whitelist it: `<%= %w[gha registry].include?(ENV["CACHE_TYPE"]) ? ENV["CACHE_TYPE"] : "registry" %>`.

Example fix

# config/deploy.yml — before
builder:
  cache:
    type: s3

# after
builder:
  cache:
    type: gha
Defensive patterns

Strategy: validation

Validate before calling

CACHE_TYPES = %w[gha registry].freeze

def valid_cache_type?(raw)
  type = raw.dig("builder", "cache", "type")
  type.nil? || CACHE_TYPES.include?(type)
end

Type guard

def kamal_cache_type?(value)
  %w[gha registry].include?(value.to_s)
end

Try / catch

begin
  Kamal::Configuration.new(create_config_files: false)
rescue ArgumentError, Kamal::ConfigurationError => e
  abort "#{e.message} — cache type must be gha or registry"
end

Prevention

When it happens

Trigger: `builder: { cache: { type: local } }` or `type: s3` in config/deploy.yml; typos like a trailing space, `GHA`, or `Registry` (the check is case-sensitive); ENV-sourced cache types such as `<%= ENV["CACHE_TYPE"] %>` resolving to something unsupported.

Common situations: Copy-pasting buildx CLI cache type names that kamal does not expose; case mismatches from environment variables; stale docs or invented values in shared config templates.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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