Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Loki By James Joyner IV · · 8 min read

Loki Error Guide: 'failed parsing config' — Fix YAML, Renamed Fields, and Env Expansion

Quick answer

Fix Loki 'failed parsing config: field not found in type': catch YAML typos, renamed fields, and env vars, then run -verify-config.

  • #loki
  • #logging
  • #troubleshooting
  • #errors
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

Loki refuses to start when it cannot parse its configuration file. The YAML unmarshaller reports the exact line and the field it could not map onto a known struct:

failed parsing config: /etc/loki/config.yaml: yaml: unmarshal errors: line 34: field boltdb_shipper not found in type ...

You may also see the wrapper form when the file cannot be read or loaded at all:

error loading config from /etc/loki/config.yaml

Loki loads the config once at startup and validates it strictly against the Go structs for the running binary version. A field not found in type message almost always means one of three things: the field is misspelled or indented into the wrong block, the field was renamed or removed in the Loki version you are running, or you meant to substitute an environment variable but the raw ${...} text leaked through. The line number in the message is your fastest lead.

Symptoms

  • Loki exits immediately at startup with failed parsing config and a specific line number.
  • The message names a field that “is not found in type”, pointing at a struct mismatch rather than bad syntax.
  • The config worked on a previous Loki version but breaks after a container image bump.
  • A ${SOME_VAR} placeholder appears literally in the effective config instead of its value.
  • kubectl logs shows a crash-loop where the pod never reaches the Loki started line.

Common Root Causes

  • YAML typo or indentation error — a field sits under the wrong parent block, so Loki cannot map it and reports it as an unknown field.
  • Field renamed or removed across versions — settings like shared_store and other index-store keys were deprecated or relocated between Loki releases, and an old manifest still references them.
  • Env substitution not enabled — the config uses ${ENV} placeholders but Loki was started without -config.expand-env=true, so the literal text fails to parse.
  • Wrong value type — a field expects an integer or duration but received a quoted string (or vice versa), triggering an unmarshal error.
  • Unescaped $ with expand-env on — a literal $ in a password or regex is treated as an env reference when -config.expand-env is enabled and must be doubled to $$.
  • Version mismatch — the manifest and the container image are on different Loki versions, so the config targets a schema the binary does not recognise.

How to diagnose

  1. Validate the config against the running binary before anything else. This parses the file exactly as startup would and prints the same error without a crash loop:

    loki -config.file=/etc/loki/config.yaml -verify-config
  2. Read the crash logs to capture the exact line and field name the unmarshaller rejected:

    kubectl logs -l app=loki --tail=50 | grep -A2 'failed parsing config'
  3. Inspect the offending line in context to confirm indentation and parent block. The field must live under the struct that actually defines it:

    # line 34 must be nested correctly, e.g. under storage_config
    storage_config:
      boltdb_shipper:
        active_index_directory: /loki/boltdb-shipper-active
        cache_location: /loki/boltdb-shipper-cache
  4. Check for leaked env placeholders by rendering the effective config; a literal ${...} means expansion is off:

    grep -n '\${' /etc/loki/config.yaml
  5. Confirm the binary version matches the config you are targeting, since renamed fields are version-specific:

    loki -version

Fixes

Validate with -verify-config and fix the exact line. The verifier reproduces the parse offline, so you can iterate quickly until it passes rather than crash-looping a pod:

loki -config.file=/etc/loki/config.yaml -verify-config && echo "config OK"

Correct the YAML indentation so the reported field sits under the block that defines it. A single stray space is enough to reparent a field into a struct that does not declare it:

storage_config:
  boltdb_shipper:
    active_index_directory: /loki/index
    cache_location: /loki/index-cache
  tsdb_shipper:
    active_index_directory: /loki/tsdb-index
    cache_location: /loki/tsdb-cache

Track down renamed or removed fields in the changelog for your version and update the key. For example, older shared_store settings were deprecated in favour of store-specific configuration; remove the stale key and use the current equivalent:

# Deprecated across newer Loki versions:
#   compactor:
#     shared_store: s3
# Current form drives the store from schema_config + common.storage instead.
compactor:
  working_directory: /loki/compactor

Enable env expansion for ${ENV} placeholders by passing the flag; without it, the literal text fails to unmarshal. Remember to double any literal $ you do not want expanded:

loki -config.file=/etc/loki/config.yaml -config.expand-env=true

Fix wrong value types so numbers and durations are unquoted where the struct expects them, and strings are quoted where needed:

limits_config:
  max_query_series: 500        # int, not "500"
  max_query_length: 721h       # duration

What to watch out for

  • Always run -verify-config in CI before shipping a config change; it catches unknown fields and type errors without touching a running cluster.
  • field not found in type is a version signal — the same config can be valid on one Loki release and invalid on the next, so pin the image and the config together.
  • With -config.expand-env=true, every literal $ becomes special; double it to $$ in passwords, regexes, and templated strings.
  • The reported line number points at where parsing failed, which is sometimes the line after the real mistake (an unclosed block bleeds into the next field).
  • Do not blindly delete a rejected field — check whether it was renamed rather than removed, or you may silently drop required behaviour.
Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.