Loading#
When a dature.load(...) call fails, the error message tells you which field broke, where in the source it came from, and why. This page walks through the failures you are most likely to hit while wiring up your first config — and one pattern for recovering from them.
All examples share the same schema
Source does not exist#
Wrong path or wrong working directory — the most common first error. dature raises a plain FileNotFoundError before any parsing happens.
"""Loading error — config file does not exist."""
from dataclasses import dataclass
from pathlib import Path
import dature
SOURCES_DIR = Path(__file__).parent / "sources"
@dataclass
class Config:
host: str
port: int
debug: bool = False
dature.load(
dature.Yaml12Source(file=SOURCES_DIR / "does_not_exist.yaml"),
schema=Config,
)
Source exists but is broken#
The file is present but the parser can't read it (here: invalid YAML indentation). dature does not swallow parser errors — the underlying exception propagates with the original file and line.
"""Loading error — config file exists but is malformed."""
from dataclasses import dataclass
from pathlib import Path
import dature
SOURCES_DIR = Path(__file__).parent / "sources"
@dataclass
class Config:
host: str
port: int
debug: bool = False
dature.load(
dature.Yaml12Source(file=SOURCES_DIR / "broken.yaml"),
schema=Config,
)
Type mismatch#
The source parses, but a value can't be coerced to the field's annotated type. dature raises a FieldLoadError with the field path, the offending value, a caret pointing at it, and the source location.
"""Loading error — value cannot be coerced to the field type."""
from dataclasses import dataclass
from pathlib import Path
import dature
SOURCES_DIR = Path(__file__).parent / "sources"
@dataclass
class Config:
host: str
port: int
debug: bool = False
dature.load(
dature.Yaml12Source(file=SOURCES_DIR / "type_mismatch.yaml"),
schema=Config,
)
| dature.errors.exceptions.DatureConfigError: Config loading errors (1)
+-+---------------- 1 ----------------
| dature.errors.exceptions.FieldLoadError: [port] invalid literal for int() with base 10: 'not_a_number'
| ├── port: not_a_number
| │ ^^^^^^^^^^^^
| └── FILE '{SOURCES_DIR}type_mismatch.yaml', line 2
+------------------------------------
Required field missing#
A field with no default value is absent from the source. The error points at the file but has no line — there is nothing in the source to highlight.
"""Loading error — required field absent from the source."""
from dataclasses import dataclass
from pathlib import Path
import dature
SOURCES_DIR = Path(__file__).parent / "sources"
@dataclass
class Config:
host: str
port: int
debug: bool = False
dature.load(
dature.Yaml12Source(file=SOURCES_DIR / "missing_field.yaml"),
schema=Config,
)
Multiple errors at once#
dature does not stop at the first error — it keeps going and reports every failed field together as an ExceptionGroup. You fix the config in one pass instead of "fix, rerun, fix, rerun".
"""Loading error — every field is checked, all errors are reported together."""
from dataclasses import dataclass
from pathlib import Path
import dature
SOURCES_DIR = Path(__file__).parent / "sources"
@dataclass
class Config:
host: str
port: int
debug: bool = False
dature.load(
dature.Yaml12Source(file=SOURCES_DIR / "multiple_errors.yaml"),
schema=Config,
)
| dature.errors.exceptions.DatureConfigError: Config loading errors (2)
+-+---------------- 1 ----------------
| dature.errors.exceptions.FieldLoadError: [port] invalid literal for int() with base 10: 'not_a_number'
| ├── port: not_a_number
| │ ^^^^^^^^^^^^
| └── FILE '{SOURCES_DIR}multiple_errors.yaml', line 2
+---------------- 2 ----------------
| dature.errors.exceptions.FieldLoadError: [debug] Expected bool, got str
| ├── debug: maybe
| │ ^^^^^
| └── FILE '{SOURCES_DIR}multiple_errors.yaml', line 3
+------------------------------------
Recovering: skip a broken source#
When merging multiple sources, a missing or malformed one can be skipped with skip_if_broken=True so the next source supplies the values:
"""Loading recovery — skip a missing source and fall back to the next one."""
from dataclasses import dataclass
from pathlib import Path
import dature
SOURCES_DIR = Path(__file__).parent / "sources"
@dataclass
class Config:
host: str
port: int
debug: bool = False
config = dature.load(
dature.Yaml12Source(
file=SOURCES_DIR / "does_not_exist.yaml",
skip_if_broken=True,
),
dature.Yaml12Source(file=SOURCES_DIR / "fallback.yaml"),
schema=Config,
)
assert config.host == "localhost"
assert config.port == 8080
assert config.debug is False
If every source fails, dature still raises — there is no value to load. The flag also has variants for skipping individual invalid fields rather than entire sources. See Merge Rules — Skipping Broken Sources for the full picture.
What's next#
- Validation — add custom rules so loading also fails when values are the wrong shape (out of range, bad regex, …), not just the wrong type.
- Merge Rules — control what happens when several sources disagree, and how to skip broken or invalid pieces.
- Debug & Reports — inspect what each source contributed before the merge happened.