henrygd/beszel · error
failed to parse config.yml: %v
Error message
failed to parse config.yml: %v
What it means
SyncSystems reads config.yml and unmarshals it with yaml.Unmarshal into the internal config struct. This error wraps any YAML parsing or structural decoding failure, meaning the file could not be interpreted as valid YAML matching the expected schema. SyncSystems aborts before touching any PocketBase records.
Source
Thrown at internal/hub/config/config.go:43
Host string `yaml:"host"`
Port uint16 `yaml:"port,omitempty"`
Token string `yaml:"token,omitempty"`
Users []string `yaml:"users"`
}
// Syncs systems with the config.yml file
func SyncSystems(e *core.ServeEvent) error {
h := e.App
configPath := filepath.Join(h.DataDir(), "config.yml")
configData, err := os.ReadFile(configPath)
if err != nil {
return nil
}
var config config
err = yaml.Unmarshal(configData, &config)
if err != nil {
return fmt.Errorf("failed to parse config.yml: %v", err)
}
if len(config.Systems) == 0 {
log.Println("No systems defined in config.yml.")
return nil
}
var firstUser *core.Record
// Create a map of email to user ID
userEmailToID := make(map[string]string)
users, err := h.FindAllRecords("users", dbx.NewExp("id != ''"))
if err != nil {
return err
}
if len(users) > 0 {
firstUser = users[0]
for _, user := range users {View on GitHub (pinned to b38fb7dafa)
Solutions
- Read the wrapped %v message — it names the exact line and YAML problem (e.g. 'line 4: cannot unmarshal !!str into int').
- Validate the file with a linter: `yamllint config.yml` or paste into a YAML validator; replace tabs with spaces.
- Fix field types to match the schema (systems list with name/host/port/users fields, port numeric).
- Restore from a known-good config or version-controlled copy, then re-run SyncSystems.
Example fix
// before: invalid config.yml
tab-indented: true
systems:
- name: web
// after: consistent two-space indentation, correct types
systems:
- name: web
host: 10.0.0.5
port: 22 Defensive patterns
Strategy: validation
Validate before calling
data, err := os.ReadFile("config.yml")
if err != nil { return err }
var probe map[string]any
if err := yaml.Unmarshal(data, &probe); err != nil {
return fmt.Errorf("config.yml is not valid YAML: %w", err)
}
if _, ok := probe["systems"]; !ok { return fmt.Errorf("config.yml missing 'systems' key") } Type guard
func isYAMLSyntaxError(err error) bool {
var te *yaml.TypeError
if errors.As(err, &te) { return false }
return err != nil // unmarshal errors that aren't TypeError are syntax errors
} Try / catch
if err := SyncSystems(); err != nil {
if strings.Contains(err.Error(), "failed to parse config.yml") {
return fmt.Errorf("fix config.yml before syncing: %w", err) // do not retry until edited
}
return err
} Prevention
- Run yamllint or an editor YAML plugin on config.yml before deploying.
- Use spaces, never tabs, and keep indentation consistent.
- Keep config.yml in version control so bad edits are reviewable and revertible.
- Add a startup-time dry-run parse of config.yml with a clear error message.
When it happens
Trigger: Calling SyncSystems when configData contains invalid YAML — bad indentation, tabs instead of spaces, unquoted special characters, or fields whose types don't match the config struct (e.g. port as a string instead of int).
Common situations: Hand-edited config.yml with a tab character or wrong indentation; YAML anchors/aliases or multiline strings misused; a value like `port: "8080"` where an int is expected; encoding issues (BOM, non-UTF8) introduced by editors.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to create new system: %v
- service name is required
- invalid token
- system missing required fields
- invalid container id
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/ecea9098372e5b5f.
Report an issue: GitHub.