Three validation depths
Depth is a deliberate choice per file. A stricter mode never changes the bytes that are written; it only changes what is rejected before writing.
| Mode | What it checks | Possible codes |
|---|---|---|
NONE | Nothing semantic. The exporter's structural checks — row width, control characters, encodability — still apply. | — |
FIELD_LEVEL | Each supplied non-empty cell against its official field definition. | INVALID_FORMAT, VALUE_OUT_OF_RANGE, TEXT_TOO_LONG, UNMAPPABLE_CHARACTER |
STRICT | Everything above, plus required fields and cross-field dependencies. | all six |
The six codes
| Code | Raised when | Usual fix |
|---|---|---|
REQUIRED_FIELD | A field the official checker marks as necessary is empty, in strict mode on an official schema. | Populate the field. Only five columns are affected: Umsatz, Soll/Haben-Kennzeichen, Konto, Gegenkonto and Belegdatum. |
INVALID_FORMAT | A value does not use DATEV's required representation — a malformed number, a date that is not a real calendar date, a flag outside its allowed set, or a control or line-separator character inside a cell. | Format the value the way DATEV expects rather than the way your locale prints it. Strip newlines and tabs from free text. |
VALUE_OUT_OF_RANGE | The value is syntactically valid but exceeds its range — too many integral digits, too many decimals, or an account number wider than the configured account length. | Check the field's maximum length and decimal places in the field reference, and check that the account length in your metadata matches the client. |
TEXT_TOO_LONG | A text value exceeds the field's maximum character count. | Truncate deliberately in your own mapping. Silent truncation is not performed for you, because losing part of a Buchungstext is a business decision. |
UNMAPPABLE_CHARACTER | The value contains a code point that Windows-1252 cannot represent. | Transliterate or replace the character before export. See the encoding reference for which characters survive. |
DEPENDENT_FIELD_MISSING | One half of a paired field group was supplied without the other, in strict mode. | Supply both halves, or neither. |
The paired fields
Strict mode enforces these pairs. Supplying either side alone produces DEPENDENT_FIELD_MISSING on the missing side.
Basis-Umsatz↔WKZ Basis-Umsatz(fields 5 and 6).Beleginfo - Art n↔Beleginfo - Inhalt nfor n = 1…8.Zusatzinformation - Art n↔Zusatzinformation- Inhalt nfor n = 1…20.
Context sharpens the checks
Some rules cannot be evaluated from the schema alone. A validation context carries the facts that make them decidable; without it, those specific checks are simply skipped rather than guessed.
- Account length narrows how wide
KontoandGegenkontomay be. - Fiscal year start and posting period let the four-digit
Belegdatumbe resolved against real calendar dates.
These checks confirm the file matches the technical schema. They say nothing about whether the bookings are correct, or whether a specific DATEV product and configuration will accept the file.
Reading errors in code
A rejected row raises DatevValidationException, which carries the full list of errors. Each error keeps its code, field number and official column name, so failures can be logged or mapped without parsing message text.
import io.github.mrtyldr.datev.core.DatevValidationError;
import io.github.mrtyldr.datev.core.DatevValidationException;
try {
file.append(columns);
} catch (DatevValidationException failure) {
for (DatevValidationError error : failure.errors()) {
log.warn("field {} ({}): {} — {}",
error.fieldNumber(),
error.canonicalKey(),
error.code(),
error.message());
}
}