Skip to content

validator crash-loops when GRAFFITI contains spaces (unquoted $FLAGS in entrypoint) #60

Description

@NandyBa

Summary

The Lighthouse validator container enters a startup crash-loop whenever the configured GRAFFITI contains a space. A graffiti with spaces worked on earlier versions, so this is a regression. While the container restarts endlessly it never loads its keys, so all validators go active_offline and miss attestations until the graffiti is changed — with no error surfaced in the UI.

Error

[INFO - entrypoint] Starting lighthouse validator with flags: ... --graffiti=my cool graffiti ...
error: unexpected argument 'cool' found

Usage: lighthouse validator_client [OPTIONS]

(here the graffiti was my cool graffiti)

Root cause

In /usr/local/bin/entrypoint.sh, every flag is flattened into a single string that is then expanded unquoted:

FLAGS="--debug-level=$LOG_LEVEL \
    --network=$NETWORK \
    validator \
    ...
    --graffiti=$VALID_GRAFFITI \
    ...
    --suggested-fee-recipient=$VALID_FEE_RECIPIENT ${MEVBOOST_FLAG} ${EXTRA_OPTS}"

# shellcheck disable=SC2086
exec lighthouse $FLAGS

The unquoted $FLAGS word-splits on every space. That is intended for splitting the optional flags (MEVBOOST_FLAG, EXTRA_OPTS), but it also splits any flag value that contains spaces. So --graffiti=my cool graffiti becomes three arguments — --graffiti=my, cool, graffiti — and Lighthouse rejects cool as an unexpected positional argument.

get_valid_graffiti() does not help — it only truncates to 32 chars, it does not sanitize or quote spaces:

valid_graffiti=$(echo "$graffiti" | cut -c 1-32)

Impact

A graffiti containing spaces is a very common choice. On the next package update / container recreation the validator silently crash-loops and stops attesting until the user notices and removes the spaces. This is easy to miss (no UI error) and directly costs attestation rewards.

Suggested fix

Build the command as a positional-parameter array and quote the values, so flag values with spaces survive word-splitting. For example:

set -- \
  --debug-level="$LOG_LEVEL" \
  --network="$NETWORK" \
  validator \
  --init-slashing-protection \
  --datadir="$DATA_DIR" \
  --beacon-nodes="$BEACON_API_URL${BACKUP_BEACON_NODES:+,$BACKUP_BEACON_NODES}" \
  --graffiti="$VALID_GRAFFITI" \
  --http --http-address 0.0.0.0 --http-port="$VALIDATOR_PORT" \
  --http-allow-origin='*' --unencrypted-http-transport \
  --metrics --metrics-address=0.0.0.0 --metrics-port=8008 --metrics-allow-origin='*' \
  --suggested-fee-recipient="$VALID_FEE_RECIPIENT"

# only the genuinely optional, multi-token flags stay unquoted
# shellcheck disable=SC2086
exec lighthouse "$@" $MEVBOOST_FLAG $EXTRA_OPTS

At minimum, --graffiti must be passed as its own quoted argument rather than embedded in an unquoted string.

Environment

  • Package: DAppNodePackage-lighthouse-generic (validator image 0.1.22)
  • Network: Gnosis
  • Lighthouse v8.2.0
  • Reproduce: set any validator graffiti that contains a space, then (re)start the validator package.

🐛 Bug flagged by NandyBa, reported by Claude.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions