denoland/deno · error · TypeError
ERR_INVALID_ARG_VALUE
ERR_INVALID_ARG_VALUE
Error message
The property 'options.tags[${i}]' must not be an empty string. Received ${tag} What it means
prepareTags() rejects empty strings as tag values: after type-checking each element of options.tags, an empty string throws ERR_INVALID_ARG_VALUE stating the property 'must not be an empty string'. This keeps tags meaningful as filter keys, since testTagFilters matching would be ambiguous with '' present.
Source
Thrown at ext/node/polyfills/testing.ts:1888
}
// Node's experimental test `tags` feature. Tags are validated (array of
// non-empty strings), canonicalized (lowercased and deduped, preserving
// declaration order), and the experimental warning is emitted once the first
// time any tag is registered.
let tagsWarningEmitted = false;
function prepareTags(tags, argName) {
if (!ArrayIsArray(tags)) {
throw new ERR_INVALID_ARG_TYPE(argName, "string[]", tags);
}
const canonical = [];
for (let i = 0; i < tags.length; i++) {
const tag = tags[i];
if (typeof tag !== "string") {
throw new ERR_INVALID_ARG_TYPE(`${argName}[${i}]`, "string", tag);
}
if (tag === "") {
throw new ERR_INVALID_ARG_VALUE(
`${argName}[${i}]`,
tag,
"must not be an empty string",
);
}
const lower = StringPrototypeToLowerCase(tag);
if (!ArrayPrototypeIncludes(canonical, lower)) {
ArrayPrototypePush(canonical, lower);
}
}
if (canonical.length > 0 && !tagsWarningEmitted) {
tagsWarningEmitted = true;
emitExperimentalWarning("Test tags");
}
return canonical;
}
function prepareOptions(name, options, fn, overrides) {View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Filter empties when splitting: input.split(',').map((s) => s.trim()).filter((s) => s !== '')
- Remove placeholder empty strings from the literal array
- Default to no tags option at all when the computed list is empty
Example fix
// before
const tags = process.env.TAGS.split(','); // 'smoke,' -> ['smoke', '']
test('x', { tags }, fn);
// after
const tags = process.env.TAGS.split(',').map((s) => s.trim()).filter(Boolean);
if (tags.length > 0) {
test('x', { tags }, fn);
} else {
test('x', fn);
} Defensive patterns
Strategy: validation
Validate before calling
function parseTags(input) {
return input
.split(',')
.map((s) => s.trim().toLowerCase())
.filter((s) => s !== '');
}
const tags = parseTags(process.env.TAGS ?? '');
test('x', tags.length > 0 ? { tags } : {}, fn); Type guard
const hasNoEmptyTags = (v) => Array.isArray(v) && v.every((t) => typeof t === 'string' && t.length > 0);
Prevention
- Filter(Boolean) after splitting comma-joined tag strings
- Remove placeholder '' entries from tag literals
- Skip the tags option entirely when the computed list is empty
When it happens
Trigger: test('x', { tags: ['smoke', ''] }, fn); tags built by splitting a comma-joined string that had a trailing comma ('smoke,').split(',') yielding an empty final element; placeholder '' for an unimplemented tag.
Common situations: Comma-splitting CLI/env tag input without filtering empties; templated tag lists where a variable was never filled in.
Related errors
- ERR_INVALID_ARG_TYPE
- Limit must be a positive integer: received ${options.limit}
- batchSize must be a positive integer: received ${batchSize}
- Invalid port (expected number): ${maybePort}
- ERR_MISSING_ARGS
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/e0719489e7cc89d0.
Report an issue: GitHub.