When handling optional/nil values, treat nil as a real input only if it’s reachable; otherwise remove dead checks. More importantly, enforce clear contracts for types/shapes so nil never reaches code paths that assume a table/string.

Practical rules: 1) Guard before indexing/iteration

2) Preserve function return contracts

3) Match conditional construction with downstream access

4) Prefer explicit fallback over misleading nil branches

5) Tests: avoid vacuous “truthy encryption”

Example patterns:

-- 1) fallback instead of dead nil-check
local new_upstream_ssl = apisix_secret.fetch_secrets(upstream_ssl, true)
new_upstream_ssl = new_upstream_ssl or upstream_ssl

-- 2) return safe type for iteration
local function names_from_proto(proto_obj)
  local names = {}
  if type(proto_obj) ~= "table" then
    return names
  end
  -- ... fill names
  return names
end

-- 3) nil-guard before method call
local data = core.request.get_body()
local ticket = data and data:match("<samlp:SessionIndex>(.+)</samlp:SessionIndex>")

-- 5) test: require non-empty string
local conf = get_conf()
local v = conf.client_rsa_private_key
assert(type(v) == "string" and v ~= "" and v ~= "plaintext")