How to Parse an ARN in Java
Part of the AWS ToolkitString[] parts = arn.split(":", 6);limit=6 means six pieces, not six splits — indexing past a short array throws ArrayIndexOutOfBoundsException
Explanation
An ARN has six colon-separated fields, but the resource field isn't guaranteed to be colon-free — a Lambda function version ARN packs a third piece into it:
arn:aws:lambda:us-east-1:123456789012:function:my-function:1Plain arn.split(":") gives you eight elements here, not six, so indexing by position grabs the wrong piece. The fix is Java's limit argument:
String[] parts = arn.split(":", 6);Per the String.split Javadoc, when the limit is positive, the pattern is applied at most limit - 1 times and the array has at most limit elements — the last one holds everything left over, including any further colons. Applied to the Lambda ARN above, parts[5] comes back as the full "function:my-function:1", untouched. Verified directly: "arn:aws:lambda:us-east-1:123456789012:function:my-function:1".split(":", 6) returns exactly six elements, not eight.
Note the limit here means the number of pieces you get back (6), the same convention Go's strings.SplitN uses — not the number of splits, which is what Python's maxsplit counts (5, for the same result). See How to Parse an ARN in Python and How to Parse an ARN in Go for those versions.
A separate, easy-to-miss trap: split's first argument is compiled as a regular expression, not matched as a literal string. It doesn't matter here since : has no special regex meaning, but splitting on a character that does — a bare ., for instance — silently does the wrong thing: "a.b.c".split(".") returns an empty array, since . as a regex matches every character. Escaping it ("\\.") or using String.split's sibling Pattern.quote fixes it. Worth remembering any time the delimiter isn't as inert as a colon.
Go a step further and index into a short array, and Java throws an unchecked ArrayIndexOutOfBoundsException rather than returning a safe empty value — verified directly against a truncated ARN: "arn:aws:s3".split(":", 6) returns only three elements, and reading parts[5] without checking parts.length first crashes instead of producing a wrong-but-safe result.
The same colons-in-the-resource trap applies to a hand-written regex, too: a pattern using [^:]+ for every group excludes colons entirely, so it won't match the Lambda ARN at all — use a greedy (.+) for the final group instead.
C# takes the same limit-as-piece-count approach — see How to Parse an ARN in C#.
For the full field-by-field breakdown of a specific ARN, see ARN Parser. For what each field means, see What Is an ARN?
Valid examples
"arn:aws:iam::123456789012:user/john".split(":", 6) → [arn, aws, iam, , 123456789012, user/john]Exactly six pieces — the limit doesn't change anything when there's nothing extra to protect.
"arn:aws:lambda:us-east-1:123456789012:function:my-function:1".split(":", 6) → [..., function:my-function:1]The sixth element absorbs both remaining colons instead of being cut off at the first one.
"arn:aws:s3:::amzn-s3-demo-bucket/Development/*".split(":", 6) → [arn, aws, s3, , , amzn-s3-demo-bucket/Development/*]region and account ID both come back as empty strings for an S3 bucket ARN — present, just empty.
Invalid examples
arn.split(":")[5] // "function", not "function:my-function:1"Splitting with no limit and indexing by position — the Lambda ARN above has 8 parts, not 6, so [5] grabs the wrong piece.
"arn:aws:s3".split(":", 6)[5]A truncated ARN produces only 3 elements — indexing [5] without checking parts.length first throws ArrayIndexOutOfBoundsException.
Pattern.compile("^arn:([^:]+):([^:]+):([^:]*):([^:]*):([^:]+)$")Every group uses [^:]+ — fails to match the Lambda ARN, since its resource part contains colons the pattern explicitly excludes.