sipeed/picoclaw · error

invalid format at line %d: %s

Error message

invalid format at line %d: %s

What it means

loadEnvFile parses each non-empty, non-comment line as KEY=value via strings.SplitN(line, "=", 2); a line without any '=' character is invalid and this error reports its 1-based line number and full content. Parsing stops at the first bad line, so earlier lines are discarded — the whole env file load fails.

Source

Thrown at pkg/mcp/manager.go:91

	defer file.Close()

	envVars := make(map[string]string)
	scanner := bufio.NewScanner(file)
	lineNum := 0

	for scanner.Scan() {
		lineNum++
		line := strings.TrimSpace(scanner.Text())

		// Skip empty lines and comments
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}

		// Parse KEY=value
		parts := strings.SplitN(line, "=", 2)
		if len(parts) != 2 {
			return nil, fmt.Errorf("invalid format at line %d: %s", lineNum, line)
		}

		key := strings.TrimSpace(parts[0])
		value := strings.TrimSpace(parts[1])

		if key == "" {
			return nil, fmt.Errorf("invalid format at line %d: empty key", lineNum)
		}

		// Remove surrounding quotes if present
		if len(value) >= 2 {
			if (value[0] == '"' && value[len(value)-1] == '"') ||
				(value[0] == '\'' && value[len(value)-1] == '\'') {
				value = value[1 : len(value)-1]
			}
		}

		envVars[key] = value

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Fix the reported line: give every entry the KEY=value form
  2. Prefix explanatory notes with # so they are treated as comments
  3. Remove shell syntax (source, export-without-=, set) — this is a plain env file, not a script
  4. Re-run: the message names the exact line number, so iterate until parsing passes

Example fix

# before (.env line 3 fails)
# myserver config
DB_HOST=localhost
secret key goes here

# after
# myserver config
DB_HOST=localhost
SECRET_KEY=...
Defensive patterns

Strategy: type-guard

Validate before calling

func lintEnvFile(path string) error {
    data, err := os.ReadFile(path)
    if err != nil {
        return err
    }
    for i, line := range strings.Split(string(data), "\n") {
        line = strings.TrimSpace(line)
        if line == "" || strings.HasPrefix(line, "#") {
            continue
        }
        if !validEnvLine(line) {
            return fmt.Errorf("line %d lacks KEY=value form: %s", i+1, line)
        }
    }
    return nil
}

Type guard

func validEnvLine(line string) bool {
    key, value, found := strings.Cut(line, "=")
    return found && strings.TrimSpace(key) != ""
}

Prevention

When it happens

Trigger: Lines like FOO (bare key), export FOO is fine only if it contains '=', but shell directives like source ~/.bashrc, set -e, or plain prose notes (not prefixed with #) all lack '=' and fail; a commented line whose leading # was lost (inline comments after values are kept as part of the value and are fine); a line-continuation backslash from a shell script pasted in.

Common situations: Pasting snippets from .bashrc into the env file; documenting entries with a bare word (FOO — the key) instead of FOO=; generated files where a value wrapped onto its own line; forgetting that only lines starting with # are comments.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/5dab31ba64a9f740. Report an issue: GitHub.