floci-io/floci · error · AwsException

ValidationException

ValidationException

Error message

1 validation error detected: Request payload must be a JSON object

What it means

Thrown by pipeline-declaration validation when pipeline.roleArn is missing or null. The roleArn is the pipeline's service role and is mandatory in both AWS and the emulator; the guard fires after the name check and before stage validation, so a missing role always fails first.

Source

Thrown at src/main/java/io/github/hectorvent/floci/core/common/SharedTagsController.java:181

        if (handler.tagsBodyIsList()) {
            ArrayNode arr = root.putArray(key);
            tags.forEach((k, v) -> {
                ObjectNode entry = arr.addObject();
                entry.put("Key", k);
                entry.put("Value", v);
            });
        } else {
            ObjectNode tagsNode = root.putObject(key);
            tags.forEach(tagsNode::put);
        }
        return root;
    }

    private Map<String, String> parseTags(TagHandler handler, JsonNode node) {
        Map<String, String> tags = new HashMap<>();
        String key = handler.tagsBodyKey();
        if (handler.strictTagValidation() && !node.isObject()) {
            throw new AwsException("ValidationException",
                    "1 validation error detected: Request payload must be a JSON object", 400);
        }
        JsonNode tagNode = node.get(key);
        if (tagNode == null || tagNode.isNull()) {
            if (handler.strictTagValidation()) {
                throw new AwsException("ValidationException",
                        "1 validation error detected: Value null at '" + key + "' failed to satisfy constraint: Member must not be null", 400);
            }
            return tags;
        }
        if (handler.tagsBodyIsList()) {
            if (!tagNode.isArray()) {
                if (handler.strictTagValidation()) {
                    throw new AwsException("ValidationException",
                            "1 validation error detected: Value at '" + key + "' failed to satisfy constraint: Member must be a list", 400);
                }
                return tags;
            }

View on GitHub (pinned to 62ff490619)

Solutions

  1. Add pipeline.roleArn with any syntactically valid ARN, e.g. arn:aws:iam::123456789012:role/service-role/my-pipeline (the emulator does not verify the role exists)
  2. Wire the role variable in your template/module so it is always set
  3. Re-check the field after SDK model changes — it is hasNonNull, so empty string also fails validation only if null; prefer a full ARN

Example fix

# before
{ "pipeline": { "name": "p", "stages": [...] } }

# after
{ "pipeline": { "name": "p", "roleArn": "arn:aws:iam::123456789012:role/my-pipeline-role", "stages": [...] } }
Defensive patterns

Strategy: validation

Validate before calling

if (pipeline.roleArn() == null || !pipeline.roleArn().startsWith("arn:")) {
    pipeline = pipeline.toBuilder()
        .roleArn("arn:aws:iam::123456789012:role/emulator-pipeline-role")
        .build();
}

Prevention

When it happens

Trigger: CreatePipeline/UpdatePipeline request whose pipeline object omits roleArn or sets it to null; role built from an unset template variable.

Common situations: Quick local pipelines assembled without an IAM role because 'the emulator does not need one'; IaC modules where the role reference is optional in the module but required by the API; refactor renaming roleArn to role.

Related errors


AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14). Data as JSON: /api/errors/af604c644568f51b. Report an issue: GitHub.