appsmithorg/appsmith · error · AppsmithPluginException

PE-JSN-4000

PE-JSN-4000

Error message

Malformed JSON: {}

What it means

Thrown by DataUtils.parseJsonBody when objectFromJson((String) body) raises JsonSyntaxException (Gson) or ParseException (Appsmith's own). This path handles the application/json content type: the raw body string is parsed into a Map or List; if the JSON is syntactically invalid the error is wrapped as PLUGIN_JSON_PARSE_ERROR with the offending body and the parser's message.

Source

Thrown at app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/DataUtils.java:142

    public Object parseJsonBody(Object body) {
        try {
            if (body instanceof String) {
                // Setting the requestBody to an empty byte array here
                // since the an empty string causes issues with a signed request.
                // If the content of the SignableRequest is null, the query string parameters
                // will be encoded and used as the contentSha256 segment of the canonical request string.
                // This causes a SignatureMatch Error for signed urls like those generated by AWS S3.
                // More detail here - https://github.com/aws/aws-sdk-java/issues/2205
                if ("" == body) {
                    return new byte[0];
                }
                Object objectFromJson = objectFromJson((String) body);
                if (objectFromJson != null) {
                    body = objectFromJson;
                }
            }
        } catch (JsonSyntaxException | ParseException e) {
            throw new AppsmithPluginException(
                    AppsmithPluginError.PLUGIN_JSON_PARSE_ERROR, body, "Malformed JSON: " + e.getMessage());
        }
        return body;
    }

    public String parseFormData(List<Property> bodyFormData, Boolean encodeParamsToggle) {
        if (bodyFormData == null || bodyFormData.isEmpty()) {
            return "";
        }

        return bodyFormData
                // Disregard keys that are null
                .stream()
                .filter(property -> property.getKey() != null)
                .map(property -> {
                    String key = property.getKey();
                    String value = (String) property.getValue();

View on GitHub (pinned to 8cd9021c24)

Solutions

  1. Validate the body with a JSON linter (e.g. jq, jsonlint.com) before running the action.
  2. If the body uses mustache bindings, check the evaluated preview in the response panel and ensure each binding resolves to valid JSON fragments.
  3. Switch the Content-Type to text/plain or raw if the body is not actually JSON.
  4. Quote all string keys and values, remove trailing commas, and use double quotes throughout.

Example fix

// before
{
  name: {{user.name}},   // unquoted key + raw binding
}

// after
{
  "name": "{{user.name}}"
}
Defensive patterns

Strategy: validation

Validate before calling

import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
String bodyStr = (String) body;
try {
    mapper.readTree(bodyStr);
} catch (Exception ex) {
    throw new IllegalArgumentException("Request body is not valid JSON: " + ex.getMessage(), ex);
}
// now safe to call dataUtils.parseJsonBody(body)

Type guard

public static boolean isValidJson(String s) {
    try {
        new ObjectMapper().readTree(s);
        return true;
    } catch (Exception e) {
        return false;
    }
}

Try / catch

try {
    Object parsed = dataUtils.parseJsonBody(body);
} catch (AppsmithPluginException e) {
    if (e.getError() == AppsmithPluginError.PLUGIN_JSON_PARSE_ERROR) {
        // fall back to sending the raw string or surface a user message
        throw new IllegalArgumentException("Fix the JSON body: " + e.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: An API action whose body content type is JSON but whose text is not valid JSON: unquoted keys, trailing commas, single quotes, unescaped control characters, a mustache template that evaluated to malformed JSON at runtime, or a body that was never meant to be JSON but whose Content-Type header says application/json.

Common situations: User writes {{input1.value}} which renders as undefined or empty, producing {}-less JSON; mixing JS expression syntax into JSON; copy/pasting a JS object literal instead of JSON; Content-Type auto-set to JSON for a raw text body.

Understand the failure class

Related errors


AI-assisted analysis of appsmithorg/appsmith@8cd9021c24 (2026-08-12). Data as JSON: /api/errors/6f9c932a28af77a5. Report an issue: GitHub.