{"record":{"id":"bcbac901f6983c60","repo":"apache/seatunnel","slug":"unexpected-json-payload-format-from-firebase","errorCode":null,"errorMessage":"Unexpected JSON payload format from Firebase","messagePattern":"Unexpected JSON payload format from Firebase","errorType":"exception","errorClass":"SeaTunnelException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-firebase/src/main/java/org/apache/seatunnel/connectors/seatunnel/firebase/source/FirebaseSourceReader.java","lineNumber":174,"sourceCode":"            SeaTunnelRowType rowType = catalogTable.getTableSchema().toPhysicalRowDataType();\n            if (rowType != null && rowType.getFieldNames() != null) {\n                return Collections.unmodifiableSet(\n                        new HashSet<>(Arrays.asList(rowType.getFieldNames())));\n            }\n        }\n        return Collections.emptySet();\n    }\n\n    /** Helper method that consistently handles single records, record maps, and JSON arrays. */\n    private void processJsonPayload(String jsonPayload, Collector<SeaTunnelRow> output)\n            throws Exception {\n        if (jsonPayload == null || jsonPayload.trim().equalsIgnoreCase(\"null\")) {\n            return;\n        }\n        String trimmed = jsonPayload.trim();\n\n        if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) {\n            throw new SeaTunnelException(\"Unexpected JSON payload format from Firebase\");\n        }\n\n        // Work queue to store objects (Maps, Lists) pending evaluation\n        Queue<Object> workQueue = new ArrayDeque<>();\n\n        // Parse initial payload once into Java Map/List\n        Object initialParsed = OBJECT_MAPPER.readValue(trimmed, Object.class);\n        workQueue.add(initialParsed);\n\n        while (!workQueue.isEmpty()) {\n            Object current = workQueue.poll();\n            if (current == null) {\n                continue;\n            }\n\n            if (current instanceof Map) {\n                @SuppressWarnings(\"unchecked\")\n                Map<String, Object> recordMap = (Map<String, Object>) current;","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-firebase/src/main/java/org/apache/seatunnel/connectors/seatunnel/firebase/source/FirebaseSourceReader.java#L156-L192","documentation":"processJsonPayload validates that the Firebase REST response starts with '{' or '[' before parsing; otherwise it throws this SeaTunnelException. It guards against payloads that are neither JSON objects/arrays — e.g. bare strings, numbers, or HTML error pages returned in place of data.","triggerScenarios":"Path pointing at a scalar leaf node (Firebase returns just \"value\" or 42 without braces); response being an HTML/plain-text error page that passed earlier status checks; empty or whitespace-only payload shaped unexpectedly.","commonSituations":"Misconfigured path selecting a leaf instead of a container node; auth issues returning non-JSON bodies; proxies injecting content; users expecting object-wrapped data from a scalar endpoint.","solutions":["Point the path at an object/array node rather than a scalar leaf value.","Curl the exact REST URL to inspect the raw body the reader receives.","Fix authentication so Firebase returns JSON data instead of error text.","Add a transform/normalization step or wrap scalars client-side if leaf values are intended."],"exampleFix":"// before\npath = \"/users/alice/email\" // leaf: \"alice@example.com\" -> throws\n// after\npath = \"/users/alice\" // object node: {\"email\": \"alice@example.com\", ...}","handlingStrategy":"validation","validationCode":"String body = fetchRaw(url);\nString t = body == null ? \"\" : body.trim();\nif (!t.startsWith(\"{\") && !t.startsWith(\"[\")) throw new IllegalStateException(\"expected JSON object/array, got: \" + t);","typeGuard":null,"tryCatchPattern":"try { reader.readSplit(split); } catch (SeaTunnelException e) { if (e.getMessage().contains(\"Unexpected JSON payload\")) { inspectRawResponse(); } throw e; }","preventionTips":["Configure paths pointing at object/array nodes, not scalar leaves","Validate the raw endpoint response with curl","Ensure auth yields JSON data, not error text","Handle leaf values with a dedicated scalar-reading path if needed"],"tags":["firebase","json","parsing","validation"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}