{"record":{"id":"d2b48672b04ec1b0","repo":"apache/seatunnel","slug":"source-position-sourceid-must-not-be-blank","errorCode":null,"errorMessage":"source position sourceId must not be blank","messagePattern":"source position sourceId 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":89,"sourceCode":"        try (PreparedStatement statement =\n                connection.prepareStatement(SourcePositionSqlStatements.SELECT_BY_SOURCE)) {\n            statement.setString(1, sourceId);\n            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","sourceCodeStart":71,"sourceCodeEnd":107,"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#L71-L107","documentation":"SqliteSourcePositionStore.save() validates that the EdgeSourcePosition carries a non-blank sourceId before persisting the position row. A null or whitespace-only sourceId would create an unusable position record, so the store rejects it with this IllegalArgumentException.","triggerScenarios":"Calling positionStore.save(position) with EdgeSourcePosition whose getSourceId() is null or only whitespace, e.g. built via a builder without setSourceId or constructed from a config where the source id option was missing.","commonSituations":"A source connector was configured without an explicit id/name; deserializing a position record from an external store with missing fields; programmatic use of the store with a partially populated EdgeSourcePosition.","solutions":["Set a non-blank sourceId on the EdgeSourcePosition before saving (e.g. position.setSourceId(\"my-source\") or the configured source name).","Check the source configuration so the id used to build the position is populated.","Validate the position object in caller code before passing it to the store.","If the position came from a serialized record, verify the source produced complete position data."],"exampleFix":"// before\nstore.save(new EdgeSourcePosition(null, partition, offset, 0));\n// after\nstore.save(new EdgeSourcePosition(\"kafka-source-1\", partition, offset, 0));","handlingStrategy":"validation","validationCode":"if (position.getSourceId() == null || position.getSourceId().trim().isEmpty()) { throw new IllegalStateException(\"sourceId required before save\"); } store.save(position);","typeGuard":"boolean hasSourceId(EdgeSourcePosition p) { return p.getSourceId() != null && !p.getSourceId().trim().isEmpty(); }","tryCatchPattern":"try { store.save(position); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"sourceId must not be blank\")) { log.error(\"Position missing sourceId: {}\", position); } throw e; }","preventionTips":["Always assign the configured source name/id when building EdgeSourcePosition.","Validate positions at source construction time, not at store time.","Deserialize positions with schema checks so sourceId cannot be dropped.","Use the source's stable configured id, not a runtime-generated label."],"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"}