{"record":{"id":"7f17e0f417d724f6","repo":"apache/seatunnel","slug":"source-position-partition-must-not-be-blank","errorCode":null,"errorMessage":"source position partition must not be blank","messagePattern":"source position partition must not be blank","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-edge-agent/seatunnel-edge-agent-starter/src/main/java/org/apache/seatunnel/edge/agent/starter/wal/sqlite/SqliteSourcePositionStore.java","lineNumber":92,"sourceCode":"            try (ResultSet resultSet = statement.executeQuery()) {\n                while (resultSet.next()) {\n                    EdgeSourcePosition position = toPosition(resultSet);\n                    positions.put(position.getPartition(), position);\n                }\n            }\n        }\n        return positions;\n    }\n\n    @Override\n    public void save(EdgeSourcePosition position) throws Exception {\n        String sourceId = position.getSourceId();\n        String partition = position.getPartition();\n        if (sourceId == null || sourceId.trim().isEmpty()) {\n            throw new IllegalArgumentException(\"source position sourceId must not be blank\");\n        }\n        if (partition == null || partition.trim().isEmpty()) {\n            throw new IllegalArgumentException(\"source position partition must not be blank\");\n        }\n        long updatedAt =\n                position.getUpdatedAt() > 0L ? position.getUpdatedAt() : System.currentTimeMillis();\n        try (PreparedStatement statement =\n                connection.prepareStatement(SourcePositionSqlStatements.UPSERT)) {\n            statement.setString(1, sourceId);\n            statement.setString(2, partition);\n            statement.setLong(3, position.getOffset());\n            statement.setBytes(4, MetadataSerde.serialize(position.getMetadata()));\n            statement.setLong(5, updatedAt);\n            statement.executeUpdate();\n        }\n    }\n\n    @Override\n    public void close() throws SQLException {\n        if (closeConnection) {\n            connection.close();","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-edge-agent/seatunnel-edge-agent-starter/src/main/java/org/apache/seatunnel/edge/agent/starter/wal/sqlite/SqliteSourcePositionStore.java#L74-L110","documentation":"SqliteSourcePositionStore.save() requires a non-blank partition value; the (sourceId, partition) pair is the upsert key for positions. A null or whitespace-only partition cannot identify which split/offset the row tracks, so save() throws this IllegalArgumentException.","triggerScenarios":"Calling positionStore.save(position) with EdgeSourcePosition whose getPartition() is null or blank — e.g. a source that reports no partition identifier for its splits.","commonSituations":"Connector implementations that do not assign partition identifiers to splits; migrating positions from another store that omitted partition; constructing positions programmatically without the partition field.","solutions":["Provide a partition identifier on the EdgeSourcePosition before saving (use a sentinel like \"default\" if the source is single-partition).","Fix the source's split/partition naming so every split carries a stable, non-empty partition string.","Validate the position object in caller code before invoking save().","Verify the upstream position deserialization preserves the partition field."],"exampleFix":"// before\nstore.save(new EdgeSourcePosition(sourceId, null, offset, 0));\n// after\nstore.save(new EdgeSourcePosition(sourceId, \"partition-0\", offset, 0));","handlingStrategy":"validation","validationCode":"if (position.getPartition() == null || position.getPartition().trim().isEmpty()) { position = position.withPartition(\"default\"); } store.save(position);","typeGuard":"boolean hasPartition(EdgeSourcePosition p) { return p.getPartition() != null && !p.getPartition().trim().isEmpty(); }","tryCatchPattern":"try { store.save(position); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"partition must not be blank\")) { log.error(\"Position missing partition: {}\", position); } throw e; }","preventionTips":["Assign stable partition identifiers in source splits.","Use a sentinel like \"default\" for single-partition sources.","Validate split naming when implementing custom connectors.","Keep partition strings consistent across restarts so upserts match."],"tags":["validation","source-position","sqlite","blank-field"],"backgroundTag":"empty-required-field","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}