neo4j/neo4j · error · IllegalArgumentException

Invalid tag. Tag must be in the format '<key>:<value>'! Prov

Error message

Invalid tag. Tag must be in the format '<key>:<value>'! Provided: '%s'

What it means

StorageTag.parse throws IllegalArgumentException when input.split(":") does not yield exactly two parts. The tag format is strictly '<key>:<value>' — one colon. Inputs with no colon ('keyvalue') or multiple colons ('k:v:extra', which splits into 3 parts) are rejected.

Source

Thrown at community/cloud/src/main/java/org/neo4j/cloud/storage/StorageTag.java:40

import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors;

public record StorageTag(String key, String value) {
    public static final String STORAGE_TAGS = "storage_tags";

    public static StorageTag parse(String input) {
        if (input == null || input.isEmpty()) {
            throw new IllegalArgumentException("Invalid tag. Tag must not be empty or null!");
        }

        try {
            var inputSplit = input.split(":");
            if (inputSplit.length != 2) {
                throw new IllegalArgumentException(
                        String.format("Invalid tag. Tag must be in the format '<key>:<value>'! Provided: '%s'", input));
            }
            return new StorageTag(inputSplit[0], inputSplit[1]);
        } catch (PatternSyntaxException e) {
            throw new IllegalArgumentException(
                    String.format("Invalid tag. Tag must be in the format '<key>:<value>'! Provided: '%s'", input));
        }
    }

    public static void setTags(Path path, Collection<StorageTag> tags) {
        if (!tags.isEmpty()) {
            if (path instanceof StoragePath storagePath) {
                storagePath.addMetadata(STORAGE_TAGS, tags);
            } else {
                throw new IllegalArgumentException("Cannot set tags on path which doesn't point to Object Storage");
            }
        }
    }

View on GitHub (pinned to f213380f81)

Solutions

  1. Rewrite the tag as exactly one colon: '<key>:<value>'
  2. If the value contains colons, encode or escape it, or split on first occurrence manually rather than via StorageTag.parse
  3. Validate with a regex like ^[^:]+:[^:]*$ before parsing and reject with a helpful message

Example fix

// before
StorageTag t = StorageTag.parse("endpoint:https://neo4j.example.com");

// after
int idx = input.indexOf(':');
StorageTag t = (idx > 0)
        ? new StorageTag(input.substring(0, idx), input.substring(idx + 1))
        : StorageTag.parse(input); // let parse() reject truly malformed input
Defensive patterns

Strategy: validation

Validate before calling

private static final Pattern TAG = Pattern.compile("^([^:]+):([^:]*)$");
boolean ok = TAG.matcher(input).matches();

Type guard

static boolean isValidTagFormat(String s) { return s != null && s.split(":", -1).length == 2 && !s.split(":", -1)[0].isEmpty(); }

Try / catch

try { return StorageTag.parse(input); } catch (IllegalArgumentException e) { throw new ConfigurationException("Bad storage tag '" + input + "', expected <key>:<value>", e); }

Prevention

When it happens

Trigger: StorageTag.parse("tag") (no colon); StorageTag.parse("a:b:c") (two colons → length 3); values containing colons such as URIs or timestamps ('key:https://x') which also split into more than 2 parts.

Common situations: Tag values that legitimately contain colons (URLs, key=value query strings, clock times); users writing 'key=value' instead of 'key:value'; copy-paste of ARNs or endpoints as tag values.

Related errors


AI-assisted analysis of neo4j/neo4j@f213380f81 (2026-08-14). Data as JSON: /api/errors/0b91edef8b841bc4. Report an issue: GitHub.