Skip to content
1Claw Academy
Curriculum/Working with Secrets2 minIntermediate · Lesson 8 of 10

Lab: find out why your variable never took effect

Lab

Set a value at the org level, resolve it, and discover which tier quietly overrode you.

Environment variables resolve through three tiers, and the lesson stated the order. This is what it feels like from the inside when you set a value and it does not appear.

  1. 1

    Model the three tiers and resolve.

    bash
    cat > /tmp/prec.py <<'EOF'
    shared = {"DATABASE_URL": "postgres://shared/app", "LOG_LEVEL": "info"}
    vault  = {"DATABASE_URL": "postgres://vault/app"}
    branch = {"DATABASE_URL": "postgres://branch/app"}
    
    def resolve(git_branch=None):
        out = dict(shared)          # shared
        out.update(vault)           # vault beats shared
        if git_branch:
            out.update(branch)      # branch override beats both
        return out
    
    print("you set DATABASE_URL at the org level to:", shared["DATABASE_URL"])
    print("preview resolves to:                     ", resolve()["DATABASE_URL"])
    print("preview on feat/x resolves to:           ", resolve("feat/x")["DATABASE_URL"])
    print("\nLOG_LEVEL, which only exists at the org level:", resolve()["LOG_LEVEL"])
    EOF
    python3 /tmp/prec.py
  2. 2

    Your org-level value is present, correct, and irrelevant for this key.

    text
    you set DATABASE_URL at the org level to: postgres://shared/app
    preview resolves to:                      postgres://vault/app
    preview on feat/x resolves to:            postgres://branch/app
    
    LOG_LEVEL, which only exists at the org level: info
  3. 3

    Clean up.

    bash
    rm /tmp/prec.py

Shadowing is silent by design. Nothing errors, nothing warns, and the value you set is stored exactly as you wrote it. LOG_LEVEL proves the org tier works fine; DATABASE_URL simply has a more specific value that wins.

  • The precedence is shared, then vault, then branch override, and more specific always wins.
  • A branch override left behind by a deleted feature branch is the version of this that is hardest to find, because nothing in the current codebase mentions it.
  • The resolve endpoint returns the final set with precedence already applied. Reading it is faster than reasoning about which tier you forgot.
Tip

When a variable is not what you expect, do not re-read your configuration. Resolve it and look at what the platform says the value is, then work backwards to which tier supplied it.

Check your understanding

3 questions
1

You set DATABASE_URL at the org level and preview still uses another value. Why?

2

Which tier is hardest to track down?

3

What is the fastest way to diagnose an unexpected value?