conductor-oss/conductor · error · RuntimeException

Failed to generate SQS policy

Error message

Failed to generate SQS policy

What it means

Thrown by SQSObservableQueue.getPolicy when ObjectMapper.writeValueAsString fails to serialize the SqsPolicy into a JSON string. The policy is built to grant sqs:SendMessage permission to a set of AWS account IDs and is attached to the queue via setQueueAttributes. The underlying JsonProcessingException (a checked Jackson exception) is wrapped in an unchecked RuntimeException, so it propagates through code that does not declare it. It indicates the policy object graph cannot be rendered to JSON at runtime.

Source

Thrown at awssqs-event-queue/src/main/java/com/netflix/conductor/sqs/eventqueue/SQSObservableQueue.java:313

            SqsPolicy policy = new SqsPolicy();
            policy.setVersion("2012-10-17");

            SqsStatement statement = new SqsStatement();
            statement.setEffect("Allow");
            statement.setAction("sqs:SendMessage");
            statement.setResource(getQueueARN());

            SqsPrincipal principal = new SqsPrincipal();
            principal.setAws(new ArrayList<>(accountIds));
            statement.setPrincipal(principal);

            policy.setStatement(List.of(statement));

            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.writeValueAsString(policy);
        } catch (JsonProcessingException e) {
            LOGGER.error("Failed to generate SQS policy for accounts: {}", accountIds, e);
            throw new RuntimeException("Failed to generate SQS policy", e);
        }
    }

    private List<String> listQueues(String queueName) {
        ListQueuesRequest listQueuesRequest =
                ListQueuesRequest.builder().queueNamePrefix(queueName).build();
        ListQueuesResponse resultList = client.listQueues(listQueuesRequest);
        return resultList.queueUrls().stream()
                .filter(queueUrl -> queueUrl.contains(queueName))
                .collect(Collectors.toList());
    }

    private void publishMessages(List<Message> messages) {
        LOGGER.debug("Sending {} messages to the SQS queue: {}", messages.size(), queueName);

        List<SendMessageBatchRequestEntry> entries =
                messages.stream()
                        .map(

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Inspect the logged cause (the JsonProcessingException) to find which field of SqsPolicy/SqsStatement/SqsPrincipal cannot be serialized.
  2. Verify the SqsPolicy/SqsStatement/SqsPrincipal classes still have public no-arg constructors and standard getters; add @JsonIgnore to non-serializable fields or annotate the problematic property.
  3. If you forked or upgraded the SQS event-queue module, diff the policy DTO classes against a known-working version and restore the serializable shape.
  4. As a workaround, serialize with a ObjectMapper registered with a JavaTimeModule / FAIL_ON_EMPTY_BEANS disabled, but prefer fixing the DTO.

Example fix

// before
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(policy);

// after (defensive config; root cause is usually the DTO shape)
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
return objectMapper.writeValueAsString(policy);
Defensive patterns

Strategy: validation

Validate before calling

// Validate accountIds are well-formed AWS account IDs before building the policy
private static final java.util.regex.Pattern ACCT =
    java.util.regex.Pattern.compile("^\\d{12}$");
boolean valid = accountIds != null
    && accountIds.stream().allMatch(a -> ACCT.matcher(a).matches());
if (!valid) return null;

Try / catch

try {
    queue.getPolicy(accountIds);
} catch (RuntimeException e) {
    if (e.getCause() instanceof JsonProcessingException jpe) {
        log.warn("SQS policy serialization failed; check SqsPolicy DTO: {}", jpe.getOriginalMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling getPolicy(List<String> accountIds) with a non-null, non-empty accountIds list when the SqsPolicy/SqsStatement/SqsPrincipal model contains a field type Jackson cannot serialize (e.g. a custom type, circular reference, or missing no-arg constructor / getters). The method is invoked internally during queue initialization when the accountIds property ('conductor.event-queues.sqs.registeredAccountIds' or equivalent) is configured.

Common situations: A version change to the SqsPolicy/SqsStatement/SqsPrincipal DTO classes that breaks Jackson serialization (removed getters, added a non-serializable field). A custom/forked policy model with fields Jackson cannot introspect. Extremely unlikely from configuration alone since accountIds is plain List<String>.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/050b88439c346528. Report an issue: GitHub.