{"record":{"id":"54be4101f5d1a129","repo":"basecamp/kamal","slug":"the-primary-role-primary-role-name-isn-t-define","errorCode":null,"errorMessage":"The primary_role #{primary_role_name} isn't defined","messagePattern":"The primary_role #(.+?) isn't defined","errorType":"validation","errorClass":"Kamal::ConfigurationError","httpStatus":null,"severity":"error","filePath":"lib/kamal/configuration.rb","lineNumber":344,"sourceCode":"      if require_destination? && destination.nil?\n        raise ArgumentError, \"You must specify a destination\"\n      end\n\n      true\n    end\n\n    def ensure_required_keys_present\n      %i[ service registry ].each do |key|\n        raise Kamal::ConfigurationError, \"Missing required configuration for #{key}\" unless raw_config[key].present?\n      end\n\n      raise Kamal::ConfigurationError, \"Missing required configuration for image\" if image.blank?\n\n      if raw_config.servers.nil?\n        raise Kamal::ConfigurationError, \"No servers or accessories specified\" unless raw_config.accessories.present?\n      else\n        unless role(primary_role_name).present?\n          raise Kamal::ConfigurationError, \"The primary_role #{primary_role_name} isn't defined\"\n        end\n\n        if primary_role.hosts.empty?\n          raise Kamal::ConfigurationError, \"No servers specified for the #{primary_role.name} primary_role\"\n        end\n\n        unless allow_empty_roles?\n          roles.each do |role|\n            if role.hosts.empty?\n              raise Kamal::ConfigurationError, \"No servers specified for the #{role.name} role. You can ignore this with allow_empty_roles: true\"\n            end\n          end\n        end\n      end\n\n      true\n    end\n","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/basecamp/kamal/blob/eee0083b38661c3707c6b6052cc89e85038a096c/lib/kamal/configuration.rb#L326-L362","documentation":"Kamal::Configuration#ensure_required_keys_present requires that the role named by `primary_role` actually exists among the keys of the `servers:` hash. The primary role (default \"web\", overridable via the top-level `primary_role:` key) is the role Kamal runs migrations, boot checks, and traffic switching against. If servers are defined but none matches the primary role name, configuration loading fails with the offending name interpolated into the message.","triggerScenarios":"Setting `primary_role: app` while `servers:` only defines roles like `web:` or `workers:`; renaming the `web` role to something else without updating `primary_role`; using a primary_role name from ERB/ENV that resolves with a typo or different capitalization.","commonSituations":"Renaming roles during a restructure and forgetting the cross-reference; copying a config that uses a custom primary_role name into a project whose servers hash still uses default naming; deleting the web role intending an accessory-only or worker-only setup.","solutions":["Add a role matching the primary role name under `servers:` (e.g. a `web:` entry with at least one host).","Or set `primary_role: <existing-role-name>` at the top level so it points at a role you actually defined.","Double-check spelling and underscores — the match is exact against the servers hash keys.","If ERB computes the role name, inspect the rendered config (`kamal config primary_role`) to see the resolved value."],"exampleFix":"# config/deploy.yml — before\nprimary_role: app\nservers:\n  web:\n    hosts:\n      - 1.2.3.4\n\n# after\nprimary_role: app\nservers:\n  app:\n    hosts:\n      - 1.2.3.4","handlingStrategy":"validation","validationCode":"def primary_role_defined?(path = \"config/deploy.yml\")\n  raw = YAML.safe_load(ERB.new(File.read(path)).result, aliases: true) || {}\n  primary = raw[\"primary_role\"] || \"web\"\n  raw[\"servers\"].is_a?(Hash) && raw[\"servers\"].key?(primary)\nend","typeGuard":null,"tryCatchPattern":"begin\n  config = Kamal::Configuration.new(create_config_files: false)\nrescue Kamal::ConfigurationError => e\n  puts \"Deploy config invalid: #{e.message}\"\n  exit 1\nend","preventionTips":["Whenever you rename a servers role, grep the whole config for the old name, including primary_role and accessories.","Set primary_role explicitly at the top of the config so the dependency is visible.","Validate the rendered config (`kamal config`) in CI for every environment overlay."],"tags":["kamal","configuration","roles","primary-role"],"backgroundTag":"config-reference-validation-failed","analyzedSha":"eee0083b38661c3707c6b6052cc89e85038a096c","analyzedAt":"2026-08-21T15:17:22.045Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}