diff --git a/flowvault/pom.xml b/flowvault/pom.xml
index 14e6e75a..66c6b7c1 100644
--- a/flowvault/pom.xml
+++ b/flowvault/pom.xml
@@ -11,7 +11,7 @@
skyflow-flowvault-java
- 3.0.0-beta.13-dev.962614b1
+ 3.0.0-beta.13-dev.7c0fb7be
jar
${project.groupId}:${project.artifactId}
Skyflow V3 SDK for the Java programming language
diff --git a/flowvault/src/main/java/com/skyflow/utils/validations/Validations.java b/flowvault/src/main/java/com/skyflow/utils/validations/Validations.java
index 39565674..667028ce 100644
--- a/flowvault/src/main/java/com/skyflow/utils/validations/Validations.java
+++ b/flowvault/src/main/java/com/skyflow/utils/validations/Validations.java
@@ -205,6 +205,37 @@ public static void validateInsertRequest(InsertRequest insertRequest) throws Sky
}
}
}
+ validateInsertRecordTokens(record.getTokens());
+ }
+ }
+
+ // Tokens are optional on an insert record, but when supplied the map must not be empty and
+ // every entry must have a non-blank key and value — mirroring the checks on data above.
+ private static void validateInsertRecordTokens(Map tokens) throws SkyflowException {
+ if (tokens == null) {
+ return;
+ }
+ if (tokens.isEmpty()) {
+ LogUtil.printErrorLog(Utils.parameterizedString(
+ ErrorLogs.EMPTY_TOKENS.getLog(), InterfaceName.INSERT.getName()
+ ));
+ throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyTokens.getMessage());
+ }
+ for (String key : tokens.keySet()) {
+ if (key == null || key.trim().isEmpty()) {
+ LogUtil.printErrorLog(Utils.parameterizedString(
+ ErrorLogs.EMPTY_OR_NULL_KEY_IN_TOKENS.getLog(), InterfaceName.INSERT.getName()
+ ));
+ throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyKeyInTokens.getMessage());
+ }
+ Object value = tokens.get(key);
+ if (value == null || value.toString().trim().isEmpty()) {
+ LogUtil.printErrorLog(Utils.parameterizedString(
+ ErrorLogs.EMPTY_OR_NULL_VALUE_IN_TOKENS.getLog(),
+ InterfaceName.INSERT.getName(), key
+ ));
+ throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyValueInTokens.getMessage());
+ }
}
}
diff --git a/flowvault/src/test/java/com/skyflow/utils/RequestFidelityTests.java b/flowvault/src/test/java/com/skyflow/utils/RequestFidelityTests.java
index 13e2506e..42b3dac9 100644
--- a/flowvault/src/test/java/com/skyflow/utils/RequestFidelityTests.java
+++ b/flowvault/src/test/java/com/skyflow/utils/RequestFidelityTests.java
@@ -528,9 +528,9 @@ private static com.skyflow.generated.rest.types.V1Upsert upsertWire(String updat
// ── insert: tokens map ───────────────────────────────────────────────────
@Test
- public void testBulkInsert_emptyTokensMapIsOmittedFromWire_knownGap() {
- // KNOWN GAP: an explicitly-set-but-empty tokens map is dropped rather than sent as {}.
- // Pinning current behavior — a caller cannot distinguish "no tokens" from "empty tokens".
+ public void testBulkInsert_emptyTokensMapIsOmittedFromWire() {
+ // Validations.validateInsertRequest rejects an explicitly-set-but-empty tokens map before
+ // the body builder runs; this pins the builder's own behavior when called directly.
Map data = new HashMap<>();
data.put("name", "john");
BulkInsertRequestRecord record = BulkInsertRequestRecord.builder()
diff --git a/flowvault/src/test/java/com/skyflow/utils/validations/ValidationsTests.java b/flowvault/src/test/java/com/skyflow/utils/validations/ValidationsTests.java
index 44a58686..7c20526a 100644
--- a/flowvault/src/test/java/com/skyflow/utils/validations/ValidationsTests.java
+++ b/flowvault/src/test/java/com/skyflow/utils/validations/ValidationsTests.java
@@ -568,6 +568,79 @@ public void testValidateInsertRequest_validRequestWithTokens() {
}
}
+ @Test
+ public void testValidateInsertRequest_emptyTokensMapThrows() {
+ ArrayList records = new ArrayList<>();
+ records.add(InsertRequestRecord.builder().tableName("table1").tokens(new HashMap<>()).build());
+ InsertRequest request = InsertRequest.builder().records(records).build();
+ try {
+ Validations.validateInsertRequest(request);
+ Assert.fail(EXCEPTION_NOT_THROWN);
+ } catch (SkyflowException e) {
+ Assert.assertEquals(ErrorMessage.EmptyTokens.getMessage(), e.getMessage());
+ }
+ }
+
+ @Test
+ public void testValidateInsertRequest_nullKeyInTokensThrows() {
+ Map tokens = new HashMap<>();
+ tokens.put(null, "tok-abc");
+ ArrayList records = new ArrayList<>();
+ records.add(InsertRequestRecord.builder().tableName("table1").tokens(tokens).build());
+ InsertRequest request = InsertRequest.builder().records(records).build();
+ try {
+ Validations.validateInsertRequest(request);
+ Assert.fail(EXCEPTION_NOT_THROWN);
+ } catch (SkyflowException e) {
+ Assert.assertEquals(ErrorMessage.EmptyKeyInTokens.getMessage(), e.getMessage());
+ }
+ }
+
+ @Test
+ public void testValidateInsertRequest_blankKeyInTokensThrows() {
+ Map tokens = new HashMap<>();
+ tokens.put(" ", "tok-abc");
+ ArrayList records = new ArrayList<>();
+ records.add(InsertRequestRecord.builder().tableName("table1").tokens(tokens).build());
+ InsertRequest request = InsertRequest.builder().records(records).build();
+ try {
+ Validations.validateInsertRequest(request);
+ Assert.fail(EXCEPTION_NOT_THROWN);
+ } catch (SkyflowException e) {
+ Assert.assertEquals(ErrorMessage.EmptyKeyInTokens.getMessage(), e.getMessage());
+ }
+ }
+
+ @Test
+ public void testValidateInsertRequest_nullValueInTokensThrows() {
+ Map tokens = new HashMap<>();
+ tokens.put("name", null);
+ ArrayList records = new ArrayList<>();
+ records.add(InsertRequestRecord.builder().tableName("table1").tokens(tokens).build());
+ InsertRequest request = InsertRequest.builder().records(records).build();
+ try {
+ Validations.validateInsertRequest(request);
+ Assert.fail(EXCEPTION_NOT_THROWN);
+ } catch (SkyflowException e) {
+ Assert.assertEquals(ErrorMessage.EmptyValueInTokens.getMessage(), e.getMessage());
+ }
+ }
+
+ @Test
+ public void testValidateInsertRequest_blankValueInTokensThrows() {
+ Map tokens = new HashMap<>();
+ tokens.put("name", " ");
+ ArrayList records = new ArrayList<>();
+ records.add(InsertRequestRecord.builder().tableName("table1").tokens(tokens).build());
+ InsertRequest request = InsertRequest.builder().records(records).build();
+ try {
+ Validations.validateInsertRequest(request);
+ Assert.fail(EXCEPTION_NOT_THROWN);
+ } catch (SkyflowException e) {
+ Assert.assertEquals(ErrorMessage.EmptyValueInTokens.getMessage(), e.getMessage());
+ }
+ }
+
// ── validateDetokenizeRequest ─────────────────────────────────────────────
@Test