denoland/deno · error · NodeError
ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS
ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS
Error message
Number of custom settings exceeds MAX_ADDITIONAL_SETTINGS
What it means
The SETTINGS packer in http2/util.ts allows at most MAX_ADDITIONAL_SETTINGS (10, util.ts:217) custom (non-standard) setting identifiers. When an 11th distinct id would be appended to the settings buffer, ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS is thrown before the frame goes out.
Source
Thrown at ext/node/polyfills/internal/http2/util.ts:471
default:
set = false;
break;
}
}
if (!set) { // not supported
let i = 0;
while (i < numCustomSettings) {
if (
settingsBuffer[IDX_SETTINGS_FLAGS + 1 + 2 * i + 1] === nsetting
) {
settingsBuffer[IDX_SETTINGS_FLAGS + 1 + 2 * i + 2] = val;
break;
}
i++;
}
if (i === numCustomSettings) {
if (numCustomSettings === MAX_ADDITIONAL_SETTINGS) {
throw new ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS();
}
settingsBuffer[IDX_SETTINGS_FLAGS + 1 + 2 * numCustomSettings + 1] =
nsetting;
settingsBuffer[IDX_SETTINGS_FLAGS + 1 + 2 * numCustomSettings + 2] =
val;
numCustomSettings++;
}
}
}
}
}
settingsBuffer[IDX_SETTINGS_FLAGS + 1] = numCustomSettings;
if (typeof settings.headerTableSize === "number") {
flags |= 1 << IDX_SETTINGS_HEADER_TABLE_SIZE;
settingsBuffer[IDX_SETTINGS_HEADER_TABLE_SIZE] = settings.headerTableSize;
}View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Trim customSettings to at most 10 distinct ids, keeping the most important first
- Prefer standard named settings (headerTableSize, initialWindowSize, maxFrameSize, ...) which do not count toward the custom limit
- Centralize settings assembly and enforce the cap with an assertion
Example fix
// before
const custom = { ...tracing, ...abTests, ...clientHints }; // 13 distinct ids -> throw
// after
const custom = Object.fromEntries(
Object.entries({ ...tracing, ...abTests, ...clientHints }).slice(0, 10),
); Defensive patterns
Strategy: validation
Validate before calling
const MAX_CUSTOM = 10;
function clampCustomSettings(cs = {}) {
return Object.fromEntries(Object.entries(cs).slice(0, MAX_CUSTOM));
}
settings.customSettings = clampCustomSettings(mergedCustom); Try / catch
try {
session = http2.connect(url, { settings });
} catch (err) {
if (err.code === "ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS") {
settings.customSettings = Object.fromEntries(
Object.entries(settings.customSettings ?? {}).slice(0, 10),
);
session = http2.connect(url, { settings });
} else throw err;
} Prevention
- Keep custom settings under 10 ids; audit merged config at startup
- Use standard named settings where possible — they do not count toward the cap
When it happens
Trigger: Passing settings.customSettings with 11+ distinct numeric keys to http2.createServer() or http2.connect(); merging custom settings from multiple modules (tracing + A/B tests + client hints) into one object that exceeds the cap.
Common situations: Feature-flag-heavy setups tunneling many experimental nghttp2 settings; config systems that deep-merge everyone's customSettings into one blob; code copied between client and server that doubles the id count.
Related errors
- ERR_HTTP2_TOO_MANY_CUSTOM_SETTINGS
- ERR_HTTP2_INVALID_SETTING_VALUE
- ERR_HTTP2_PUSH_DISABLED
- ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH
- ERR_HTTP2_INVALID_SETTING_VALUE
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/69f4976efe2de082.
Report an issue: GitHub.