floci-io/floci · error · AwsException
ActionTypeAlreadyExistsException
ActionTypeAlreadyExistsException
Error message
Action type already exists
What it means
Thrown by createCustomActionType (CodePipelineService.java:481) when a custom action type with the same category+provider+version id already exists in the account store. The id string is the composite key, so any collision on those three fields — even with different settings — triggers ActionTypeAlreadyExistsException.
Source
Thrown at src/main/java/io/github/hectorvent/floci/services/codepipeline/CodePipelineService.java:481
putExecution(rollback);
return started;
}
private ObjectNode overrideStageCondition(JsonNode request, String region, String account) {
requireExecution(account, region, text(request, "pipelineName"), text(request, "pipelineExecutionId"));
return mapper.createObjectNode();
}
private ObjectNode listRuleExecutions(JsonNode request, String region, String account) {
requirePipeline(account, region, text(request, "pipelineName"));
return emptyPage("ruleExecutionDetails");
}
private ObjectNode createCustomActionType(JsonNode request, String region, String account) {
String id = actionTypeId(request.path("category").asText(), "Custom",
request.path("provider").asText(), request.path("version").asText());
if (itemStore.getForAccount(account, itemKey(region, "action", id)).isPresent()) {
throw new AwsException("ActionTypeAlreadyExistsException", "Action type already exists", 400);
}
ObjectNode actionType = mapper.createObjectNode();
actionType.setAll((ObjectNode) request.deepCopy());
actionType.putObject("id")
.put("category", request.path("category").asText())
.put("owner", "Custom")
.put("provider", request.path("provider").asText())
.put("version", request.path("version").asText());
storeItem(account, region, "action", id, "Active", actionType);
return mapper.createObjectNode().set("actionType", actionType);
}
private ObjectNode updateActionType(JsonNode request, String region, String account) {
JsonNode identifier = request.path("actionType");
String id = actionTypeId(identifier.path("category").asText(), identifier.path("owner").asText(),
identifier.path("provider").asText(), identifier.path("version").asText());
CodePipelineStoredItem existing = requireItem(account, region, "action", id, "ActionTypeNotFoundException");
existing.setData(request.deepCopy());View on GitHub (pinned to 62ff490619)
Solutions
- ListActionTypes first, filter owner=Custom, and skip creation when the id already exists.
- Delete the stale custom action type before re-registering, if the semantics changed.
- Make registration scripts idempotent (check-then-create) and use unique provider names per team.
Example fix
// before
client.create_custom_action_type(category='Build', provider='Jenkins', version='1', ...)
// after
existing = [a for a in client.list_action_types().get('actionTypes', [])
if a['id']['owner'] == 'Custom']
have = {(a['id']['category'], a['id']['provider'], a['id']['version']) for a in existing}
if ('Build', 'Jenkins', '1') not in have:
client.create_custom_action_type(category='Build', provider='Jenkins', version='1', ...) Defensive patterns
Strategy: validation
Validate before calling
existing = {(a['id']['category'], a['id']['provider'], a['id']['version'])
for a in client.list_action_types().get('actionTypes', [])
if a['id']['owner'] == 'Custom'}
if ('Build', 'MyProvider', '1') not in existing:
client.create_custom_action_type(category='Build', provider='MyProvider',
version='1', inputArtifactDetails=..., outputArtifactDetails=...) Try / catch
try:
client.create_custom_action_type(...)
except ClientError as e:
if e.response['Error']['Code'] == 'ActionTypeAlreadyExistsException':
logger.info('custom action already registered; skipping')
else:
raise Prevention
- Make bootstrap scripts check-then-create instead of unconditional create.
- Use team-unique provider names to avoid collisions in shared accounts.
- Bump the version field when action semantics change instead of re-registering the same id.
When it happens
Trigger: CreateCustomActionType(category=X, provider=P, version=V) called twice; re-running bootstrap scripts that register the same custom action; two teams independently registering provider 'Jenkins' version '1'.
Common situations: Non-idempotent setup scripts run per CI job; environment rebuilds without cleanup; provider naming collisions across projects sharing one account.
Related errors
- PipelineNameInUseException
- TLS enabled but no certificate provided and self-signed gene
- ${description} file not found or not readable: ${path}
- BadRequestException
- ValidationException
AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14).
Data as JSON: /api/errors/1feb42fb72c89f18.
Report an issue: GitHub.