nats-io/nats-server · error

config is invalid (%s:%d:%d)

Error message

config is invalid (%s:%d:%d)

What it means

parse() walks lexer items and rejects configs that end while a key was pushed but never assigned a value (and the last token wasn't the closing '}'). It reports "config is invalid" with file:line:pos of EOF. This catches truncated or JSON-like configs that stop after a key without a value.

Source

Thrown at conf/parse.go:212

	p := newParser(data, "", false)
	p.envVarReferences = parent.envVarReferences
	if err := p.parse(""); err != nil {
		return nil, err
	}
	return p, nil
}

func (p *parser) parse(fp string) error {
	p.pushContext(p.mapping)

	var prevItem item
	for {
		it := p.next()
		if it.typ == itemEOF {
			// Here we allow the final character to be a bracket '}'
			// in order to support JSON like configurations.
			if prevItem.typ == itemKey && prevItem.val != mapEndString {
				return fmt.Errorf("config is invalid (%s:%d:%d)", fp, it.line, it.pos)
			}
			break
		}
		prevItem = it
		if err := p.processItem(it, fp); err != nil {
			return err
		}
	}
	return nil
}

func (p *parser) next() item {
	return p.lx.nextItem()
}

func (p *parser) pushContext(ctx any) {
	p.ctxs = append(p.ctxs, ctx)
	p.ctx = ctx

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Open the file:line:pos from the error and supply a value for the dangling key
  2. Restore the truncated tail of the config (check version control or backup)
  3. For JSON-style configs, ensure valid JSON: every key has a value and braces balance
  4. Run `nats-server -t -c file.conf` to syntax-check before deploying

Example fix

// before
listen: 4222
http
// after
listen: 4222
http: 8222
Defensive patterns

Strategy: validation

Validate before calling

// quick sanity check before parsing: braces balanced and non-empty
func configLooksComplete(data []byte) error {
    depth := 0
    for _, r := range string(data) {
        if r == '{' { depth++ }
        if r == '}' { depth-- }
    }
    if depth != 0 {
        return errors.New("unbalanced braces: config likely truncated")
    }
    return nil
}

Try / catch

cfg, err := conf.ParseFile(fp)
if err != nil {
    if strings.Contains(err.Error(), "config is invalid (") {
        log.Fatalf("config %s ends with a dangling key — check the tail of the file", fp)
    }
    return err
}

Prevention

When it happens

Trigger: A config file ends right after a key with no value or closing brace, e.g. file truncated mid-edit or a JSON-style config missing a value before EOF; parse is called recursively (includes/env) via parse/parseEnv.

Common situations: Cut-and-paste losing the last lines of nats.conf; an editor dropping a trailing value; hand-written JSON-like config ending in a dangling key such as `{ "port": 4222, "http" }`.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/8df2321917bcd424. Report an issue: GitHub.