onetimesecret/onetimesecret · error · Onetime::ConfigError
#{name} is set to an unrecognized boolean (#{value.length} c
Error message
#{name} is set to an unrecognized boolean (#{value.length} chars, sha256:#{::Digest::SHA256.hexdigest(value)[0, BOOL_DIGEST_LENGTH]}). Use one of #{TRUTHY_VALUES.join('/')} or #{FALSEY_VALUES.join('/')}, or leave unset. What it means
Onetime::Utils::Strings.strict_bool! resolves operator-supplied booleans strictly (ADR-033): after strip+downcase, blank means unset and returns the caller's default; otherwise the value must be exactly one of TRUTHY_VALUES (1/true/yes/on/y/t) or FALSEY_VALUES (0/false/no/off/n/f). Anything else raises Onetime::ConfigError rather than silently disabling a default-ON control. The message deliberately never echoes the value — it may be a misrouted credential — and instead reports its length plus an 8-hex-char SHA-256 tag you can recompute locally (lib/onetime/utils/strings.rb:299).
Source
Thrown at lib/onetime/utils/strings.rb:307
# to confirm which value a log line refers to. Honest caveat: 8 hex
# characters of a low-entropy value like "ture" is brute-forceable —
# which is fine, because low-entropy values are exactly the case that
# was never sensitive.
#
# @param name [String] Flag name, for the error message (e.g. 'RABBITMQ_VERIFY_PEER')
# @param raw [Object] Raw value as supplied
# @param default [Boolean] Value to use when raw is unset/blank
# @return [Boolean]
# @raise [Onetime::ConfigError] if raw is present but not a recognized token
def strict_bool!(name, raw, default:)
# Normalize exactly once so the blank guard and the token tables can
# never disagree about what normalization means.
value = raw.to_s.strip.downcase
return default if value.empty?
return true if TRUTHY_VALUES.include?(value)
return false if FALSEY_VALUES.include?(value)
raise Onetime::ConfigError,
"#{name} is set to an unrecognized boolean " \
"(#{value.length} chars, sha256:#{::Digest::SHA256.hexdigest(value)[0, BOOL_DIGEST_LENGTH]}). " \
"Use one of #{TRUTHY_VALUES.join('/')} or #{FALSEY_VALUES.join('/')}, or leave unset."
end
module_function :strict_bool!
private
# Masks a single email address string
# @param raw [String] Raw email address to mask
# @return [String] Masked email address
def mask_email_address(raw)
addr = ::Mail::Address.new(raw)
return mask_unparsed_address(raw) unless addr.local && addr.domain
local = mask_string_head(addr.local, EMAIL_MASK_MIN_LOCAL)
domain = mask_domain(addr.domain)
"#{local}@#{domain}"View on GitHub (pinned to f81295e41b)
Solutions
- Set the flag to a recognized token — 1/true/yes/on/y/t or 0/false/no/off/n/f — or delete the line to take the default.
- To identify a mystery value, recompute the tag and compare with the sha256: prefix in the message: ruby -rdigest -e 'puts Digest::SHA256.hexdigest(ARGV[0].strip.downcase)[0,8]' 'suspected-value'.
- Remove literal quotes or stray characters introduced by systemd units or docker env files.
- If the reported length looks like a credential, grep your environment for a value misrouted into this flag's name.
Example fix
# before — typo meant to disable peer verification, fails fast at boot RABBITMQ_VERIFY_PEER=ture # Onetime::ConfigError: RABBITMQ_VERIFY_PEER is set to an unrecognized boolean (4 chars, sha256:...) # after — recognized token (or leave unset for the default) RABBITMQ_VERIFY_PEER=true
Defensive patterns
Strategy: type-guard
Validate before calling
# Lint boolean flags before boot
ok = Onetime::Utils::Strings::TRUTHY_VALUES + Onetime::Utils::Strings::FALSEY_VALUES
%w[RABBITMQ_VERIFY_PEER SMTP2GO_FASTACCEPT].each do |flag|
v = ENV[flag].to_s.strip.downcase
next if v.empty? || ok.include?(v)
abort "#{flag} is not a recognized boolean (#{ok.join('/')}) — fix or unset"
end Type guard
# Recognizer matching strict_bool!'s normalization exactly
module BoolGuard
TOKENS = Onetime::Utils::Strings::TRUTHY_VALUES +
Onetime::Utils::Strings::FALSEY_VALUES
def self.strict_bool_token?(raw)
TOKENS.include?(raw.to_s.strip.downcase)
end
end
BoolGuard.strict_bool_token?(ENV['SMTP2GO_FASTACCEPT']) # false => strict_bool! would raise Try / catch
begin
fast = Onetime::Utils::Strings.strict_bool!('SMTP2GO_FASTACCEPT',
ENV['SMTP2GO_FASTACCEPT'], default: false)
rescue Onetime::ConfigError => ex
abort "Boot aborted — fix the environment first: #{ex.message}"
end Prevention
- Run an env-var lint step (CI or container entrypoint) over every boolean flag before the app boots.
- Never quote boolean values in systemd Environment= or docker env files.
- Standardize on true/false in automation; treat any other spelling as a typo to fix at the source.
When it happens
Trigger: Setting any flag consumed through strict_bool! — callers include enabled?, automatic_tax?, smtp2go_fastaccept/coerce_fastaccept, and QueueConfig flags such as RABBITMQ_VERIFY_PEER — to a token outside the tables: typos like 'ture' or 'flase', words like 'enabled'/'check', '1|0', or literal quotes left around the value.
Common situations: Hand-edited .env typo; systemd Environment= or docker --env-file quoting that leaves literal quotes in the value; a CI secret accidentally exported under a boolean flag's name (the long random string shows up as a length plus sha256 tag); 'TRUE' works (downcased) but 'yes please' does not.
Related errors
- Member not found
- Invalid redis_url: #{ex.message}
- SIGNIN_BACKFILL_CREATED_BEFORE is not parseable (#{raw.inspe
- Failed to parse incoming-config response from server
- Unexpected response format
AI-assisted analysis of onetimesecret/onetimesecret@f81295e41b (2026-08-23).
Data as JSON: /api/errors/3b66322a7b50a9c3.
Report an issue: GitHub.