conductor-oss/conductor · error · NonTransientException

Error de-serializing json

Error message

Error de-serializing json

What it means

Thrown by CassandraBaseDAO.readValue when ObjectMapper.readValue fails while deserializing a JSON string from Cassandra into a typed object. IOException is wrapped in NonTransientException. Used to reconstruct EventHandler/WorkflowModel/TaskModel from stored text payloads.

Source

Thrown at cassandra-persistence/src/main/java/com/netflix/conductor/cassandra/dao/CassandraBaseDAO.java:316

                .addPartitionKey(EVENT_HANDLER_NAME_KEY, DataType.text())
                .addClusteringColumn(EVENT_EXECUTION_ID_KEY, DataType.text())
                .addColumn(PAYLOAD_KEY, DataType.text())
                .getQueryString();
    }

    String toJson(Object value) {
        try {
            return objectMapper.writeValueAsString(value);
        } catch (JsonProcessingException e) {
            throw new NonTransientException("Error serializing to json", e);
        }
    }

    <T> T readValue(String json, Class<T> clazz) {
        try {
            return objectMapper.readValue(json, clazz);
        } catch (IOException e) {
            throw new NonTransientException("Error de-serializing json", e);
        }
    }

    void recordCassandraDaoRequests(String action) {
        recordCassandraDaoRequests(action, "n/a", "n/a");
    }

    void recordCassandraDaoRequests(String action, String taskType, String workflowType) {
        Monitors.recordDaoRequests(DAO_NAME, action, taskType, workflowType);
    }

    void recordCassandraDaoEventRequests(String action, String event) {
        Monitors.recordDaoEventRequests(DAO_NAME, action, event);
    }

    void recordCassandraDaoPayloadSize(
            String action, int size, String taskType, String workflowType) {
        Monitors.recordDaoPayloadSize(DAO_NAME, action, taskType, workflowType, size);

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Read the wrapped IOException cause to find the unmappable field.
  2. If a model field type changed, make the old form backward-compatible (custom deserializer, @JsonAlias, or nullable/optional field).
  3. Run a data audit for rows whose payload cannot be parsed and migrate or quarantine them.
  4. Pin a consistent ObjectMapper and Jackson version across read/write paths.

Example fix

// before
throw new NonTransientException("Error de-serializing json", e);

// after
throw new NonTransientException(
    "Error de-serializing json into " + clazz.getName() + ": " + json, e);
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate payload is parseable JSON of the expected type before trusting stored rows
objectMapper.readReturnValue(json, EventHandler.class); // surface schema drift early

Try / catch

try {
    return readValue(json, clazz);
} catch (NonTransientException e) {
    log.warn("Failed to deserialize into {}: {}", clazz.getSimpleName(), json);
    throw e;
}

Prevention

When it happens

Trigger: Calling readValue(String json, Class<T> clazz) on a payload whose JSON no longer matches the target class schema — missing fields, type changes, or truncated/corrupt JSON read from Cassandra.

Common situations: Schema migration that changed a model field type or removed a required field, making stored rows fail to deserialize. Corrupted/truncated payload text. A Jackson version change tightening deserialization defaults.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/2358cc8c58959857. Report an issue: GitHub.