Docs / EventSourcingDB / Errors / import-malformed

import-malformed

A line of the import is not an event that an import takes.

  • Route: import-events
  • Description: import is malformed: <reason>, with the reason:
    • for a line of the wrong shape, every field that a line does not have, every null, and every value of the wrong JSON type, each by its place as a JSON pointer, ordered by their places, with the fields of the line by their names, separated by semicolons, at most 10 of them, and ending with ; and more where there are more, such as /hash: unknown field; /predecessorhash: unknown field; /signature: unknown field, /traceparent: null is not allowed, or /subject: expected a string
    • for a specversion that is left out or empty, specversion is missing: expected '1.0', and for any other than 1.0, specversion is unsupported: expected '1.0'
    • for a datacontenttype that is left out or empty, datacontenttype is missing: expected 'application/json', and for any other than application/json, datacontenttype is unsupported: expected 'application/json'
    • for an id that is left out or empty, event ID is missing: expected a non-negative integer of at most 9223372036854775807 in a string, such as '42'
    • for a time that is left out or empty, time is missing: expected a timestamp as defined by RFC 3339, such as '2025-04-15T10:00:00.183492071Z'
    • for a time before 1970, time is before 1970-01-01T00:00:00Z, the earliest time that an event can have
    • for a tracestate without a traceparent, tracestate is set without a traceparent
    • for any other value that is missing or malformed, a text that names the value, for example subject is missing: expected a slash-separated path such as '/books/42', or event ID is malformed: expected a non-negative integer of at most 9223372036854775807 in a string, such as '42'
    • for a line that is longer than any event of an import can be, line <line> is longer than any event of an import can be, which is at most 399360 bytes
    • for a line that is not JSON, the message of the JSON decoder, such as unexpected end of JSON input
  • Details: line, the number of the line in the request body, counting from 1.

Why It Happens#

An import reads the events line by line, checks that each line is an event that an import takes, and stops at the first line that is not. Each line is a plain CloudEvent with exactly the fields specversion, id, source, subject, type, time, datacontenttype, and data, and, where the event has them, traceparent and tracestate, which are strings. A tracestate requires a traceparent, as W3C Trace Context does, and as writing events requires it. Any other field is refused, among them hash, predecessorhash, and signature, since the import computes the hashes itself, and extensions of CloudEvents, since an event has no place to keep them.

The shape of a line is checked first, as the shape of a request body is: every field that a line does not have, every null, and every value of the wrong JSON type is named, so that a line written by another tool shows all of its problems of shape at once. Its values are checked next, in the order in which export-events writes them, as writing events checks them, and the first that is missing or wrong is reported. Every key of a line is read exactly as it is documented: a key spelled otherwise, such as Subject, is a field that a line does not have.

The ID of an event is written without a sign or a leading zero, so that 07 cannot stand for 7. That the IDs begin at 0 and follow each other without gaps is checked as the events are imported, and an ID that does not is reported as event-chain-broken instead. The time of an event is a timestamp as RFC 3339 defines it, and is stored in UTC; it can lie no earlier than 1970-01-01T00:00:00Z.

An import also bounds each line, to 390 KiB, or 399,360 bytes, its newline aside, and refuses a longer line without reading it to its end, so that a single line cannot take up the memory of the server. The bound is six times the largest event that the database stores and 1 KiB for the names of its fields: JSON lets a client write any character as an escape of six bytes, such as \u0061 for a, as Python's json.dumps writes every character beyond ASCII by default, and every event that the database stores imports however its characters are escaped. An event that is larger than the maximum event size once its line is decoded is reported as event-too-large instead. See Limits.

Typical causes are lines that another tool wrote with fields of its own, such as the events that read-events sends, taken out of their envelopes with their hashes and their signature; lines that were changed by hand; a line that was cut; and an empty line, as when two files are joined with an empty line between them.

How to Fix It#

Remove or repair the line that line names, and send the events again. EventSourcingDB has removed what it imported so far, so the database holds no events again, and the schemas that were registered before the import are still there. Resending the request unchanged fails the same way.

Example#

For an import whose second line holds an event as read-events sends it as the data of its envelope, with its hashes and its signature, EventSourcingDB answers with this error, as a line of the stream, and then ends the stream with its end item:

{
  "type": "error",
  "data": {
    "code": "https://docs.eventsourcingdb.io/errors/import-malformed",
    "description": "import is malformed: /hash: unknown field; /predecessorhash: unknown field; /signature: unknown field",
    "details": {
      "line": 2
    }
  }
}