opf/openproject · critical · ArgumentError

Configuration value for environment variable '#

Error message

Configuration value for environment variable '#{env_var_name}' is invalid: #{e.message}

What it means

Every OPENPROJECT_* environment override is parsed with YAML.safe_load (permitted classes: Symbol and Date) by Settings::Definition.extract_value_from_env so that typed values (integers, booleans, arrays, hashes) can be expressed in env vars. Any StandardError — typically Psych::SyntaxError from malformed YAML or Psych::DisallowedClass from an unpermitted tag — is wrapped in ArgumentError naming the env var and the underlying parser message. It is raised when the setting override is resolved, effectively at startup.

Solutions

  1. Quote values containing YAML metacharacters: OPENPROJECT_APP__TITLE='"Hello: World"'
  2. Use valid YAML for typed values: arrays as "[a, b]", hashes as "{a: b}", booleans as true/false, numbers bare
  3. Remember the special cases: '' passes through as the raw string, !!str '' gives a literal empty string, !!null gives nil
  4. Re-run startup after fixing — the error names the exact env var and includes the parser's reason

Example fix

# before — boot fails with
#   ArgumentError: Configuration value for environment variable 'OPENPROJECT_APP__TITLE' is invalid:
#   mapping values are not allowed in this context
environment:
  OPENPROJECT_APP__TITLE: "Hello: World"

# after
environment:
  OPENPROJECT_APP__TITLE: "'Hello: World'"   # or quote inside the value: "'Hello: World'"
Defensive patterns

Strategy: validation

Validate before calling

# CI/deploy check: parse every OPENPROJECT_* override with the same YAML rules
require "yaml"
ENV.grep(/\AOPENPROJECT_/).each do |key|
  value = ENV.fetch(key)
  next if value == "" # passed through verbatim by the app
  YAML.safe_load(value, permitted_classes: [Symbol, Date])
rescue StandardError => e
  abort "Invalid #{key}: #{e.message}"
end

Prevention

When it happens

Trigger: An OPENPROJECT_* value that is invalid YAML or instantiates a disallowed class: an unquoted scalar containing ': ' such as OPENPROJECT_APP__TITLE=Hello: World (Psych::SyntaxError: mapping values are not allowed in this context), unbalanced quotes/brackets, undefined YAML aliases (*ref), or explicit tags like !ruby/object. Note: an empty string is passed through verbatim; !!str '' yields a literal empty string and !!null yields nil.

Common situations: docker-compose/Kubernetes env values containing colons, asterisks or brackets without quoting; values copy-pasted from YAML files losing their quotes; prose/URL-with-colon values set as bare scalars; secrets or multi-line values injected with characters YAML treats specially.

Related errors


AI-assisted analysis of opf/openproject@d9742c43f3 (2026-08-21). Data as JSON: /api/errors/973a14eff976849b. Report an issue: GitHub.

Appendix: source

Thrown at config/constants/settings/definition.rb:1875

      #
      # @param env_var_name [String] The environment variable name.
      # @param env_var_value [String] The string from which to extract the actual value.
      # @return A ruby object (e.g. Integer, Float, String, Hash, Boolean, etc.)
      # @raise [ArgumentError] If the string could not be parsed.
      def extract_value_from_env(env_var_name, env_var_value)
        # YAML parses '' as false, but empty ENV variables will be passed as that.
        # To specify specific values, one can use !!str (-> '') or !!null (-> nil)
        return env_var_value if env_var_value == ""

        parsed = load_yaml(env_var_value)

        if parsed.is_a?(String)
          env_var_value
        else
          parsed
        end
      rescue StandardError => e
        raise ArgumentError, "Configuration value for environment variable '#{env_var_name}' is invalid: #{e.message}"
      end

      def load_yaml(source)
        YAML::safe_load(source, permitted_classes: [Symbol, Date])
      end
    end

    private

    attr_accessor :serialized,
                  :writable

    def value_override?
      !resolve_value_override.nil?
    end

    def resolve_value_override
      self.class.value_overrides[name.to_sym]&.each do |block|

View on GitHub (pinned to d9742c43f3)