floci-io/floci · error · AwsException
BadRequestException
BadRequestException
Error message
Invalid resource ARN: " + arn
What it means
Thrown by API Gateway v1 tagging operations (TagResource/UntagResource/ListTagsForResource) when the supplied Resource-arn does not contain the literal segment '/restapis/'. Floci's ApiGatewayTagHandler.apiIdFromArn() splits the ARN on '/restapis/' and requires at least two parts; anything else (an ARN for a different resource type, a raw API id, or a malformed string) cannot yield an apiId and is rejected as BadRequestException (HTTP 400).
Source
Thrown at src/main/java/io/github/hectorvent/floci/services/apigateway/ApiGatewayTagHandler.java:56
@Override
public Map<String, String> listTags(String region, String arn) {
return service.getTags(region, apiIdFromArn(arn));
}
@Override
public void tagResource(String region, String arn, Map<String, String> tags) {
service.tagResource(region, apiIdFromArn(arn), tags);
}
@Override
public void untagResource(String region, String arn, List<String> tagKeys) {
service.untagResource(region, apiIdFromArn(arn), tagKeys);
}
private static String apiIdFromArn(String arn) {
String[] parts = arn.split("/restapis/");
if (parts.length < 2) {
throw new AwsException("BadRequestException", "Invalid resource ARN: " + arn, 400);
}
return parts[1].split("/")[0];
}
}
View on GitHub (pinned to 62ff490619)
Solutions
- Use the canonical v1 RestApi ARN format: arn:aws:apigateway:<region>::/restapis/<apiId> (empty account field is correct for apigateway).
- For HTTP APIs (v2) use the apigatewayv2 TagResource operation and its ARN format arn:aws:apigateway:<region>::/apis/<apiId> instead of the v1 endpoint.
- Retrieve the correct ARN from the API's ARN attribute (GetRestApi / Fn::GetAtt RestApi.Arn) rather than hand-building it.
- Add a preflight assertion in your tagging code that the ARN contains '/restapis/' before invoking the API.
Example fix
# before aws --endpoint-url http://localhost:4566 apigateway tag-resource \ --resource-arn arn:aws:apigateway:us-east-1::/apis/abc1234567 --tags k=v # after (v1 REST API) aws --endpoint-url http://localhost:4566 apigateway tag-resource \ --resource-arn arn:aws:apigateway:us-east-1::/restapis/abc1234567 --tags k=v
Defensive patterns
Strategy: validation
Validate before calling
// Java: build and check the v1 ARN before tagging
String arn = "arn:aws:apigateway:" + region + "::/restapis/" + apiId;
if (arn.split("/restapis/").length < 2 || arn.split("/restapis/")[1].isBlank()) {
throw new IllegalArgumentException("Not a v1 RestApi ARN: " + arn);
}
service.tagResource(region, arn, tags); Try / catch
catch (AwsException e) {
if ("BadRequestException".equals(e.getCode()) && e.getMessage().contains("Invalid resource ARN")) {
// ARN shape is wrong: log and surface a config error, do not retry
throw new ConfigurationException("Tagging requires arn:aws:apigateway:<region>::/restapis/<apiId>", e);
}
throw e;
} Prevention
- Take ARNs from the owning API (GetRestApi's ARN attribute) instead of hand-building them.
- Keep v1 (/restapis/) and v2 (/apis/) ARN builders as separate named constants.
- Add a shared ARN format unit test for every resource type you tag.
When it happens
Trigger: Calling aws apigateway tag-resource --resource-arn <arn> with an ARN whose resource part is not 'restapis/<apiId>' — e.g. arn:aws:apigateway:us-east-1::/usageplans/abc123, a RestApi id like 'abc123' with no ARN wrapper, or a v2 (HTTP API) ARN of the form ...:/apis/<id> routed at the v1 tagging endpoint.
Common situations: Mixing API Gateway v1 (REST) and v2 (HTTP) ARN formats — v2 uses /apis/, not /restapis/. Copying an execute-api ARN, a stage ARN, or passing the API id directly because the console shows it. Tagging usage plans, domain names, or other API Gateway sub-resources whose ARNs this handler does not model.
Understand the failure class
Background: BadRequestException (HTTP 400) — NestJS 'Bad Request' Errors: Why They Fire and How to Fix Them — this error's family across 4 libraries.
Related errors
- BadRequestException
- MissingAction
- TLS enabled but no certificate provided and self-signed gene
- ValidationException
- ValidationException
AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14).
Data as JSON: /api/errors/846a4563dfbde9c6.
Report an issue: GitHub.