usebruno/bruno · error · Error
HeaderList is read-only (response headers cannot be modified
Error message
HeaderList is read-only (response headers cannot be modified)
What it means
Thrown by HeaderList write methods (add, upsert, remove, clear, repopulate, populate, assimilate) when the HeaderList instance is in read-only mode. The #assertWritable guard at header-list.js:121-124 checks the private #writable flag, which is set to false for response header lists. Response headers are immutable snapshots; only request headers are writable.
Source
Thrown at packages/bruno-js/src/header-list.js:123
}
});
this.#req = source;
} else {
// Static read-only mode — snapshot of response headers
const rawHeaders = (source && source.headers) || {};
super({
keyProperty: 'key',
valueProperty: 'value',
items: Object.entries(rawHeaders).map(([key, value]) => ({ key, value }))
});
this.#req = null;
}
this.#writable = writable;
}
#assertWritable() {
if (!this.#writable) {
throw new Error('HeaderList is read-only (response headers cannot be modified)');
}
}
// ── Case-insensitive key helpers ──────────────────────────────────────
/**
* Case-insensitive string comparison.
* @param {string} a
* @param {string} b
* @returns {boolean}
*/
static #ciEquals(a, b) {
return typeof a === 'string' && typeof b === 'string'
? a.toLowerCase() === b.toLowerCase()
: a === b;
}
/**View on GitHub (pinned to 9bdd81c7bd)
Solutions
- Modify request headers instead: use req.headerList.add() / req.setHeader() for outgoing requests.
- If you need to transform response headers for assertions, copy them to a plain object first instead of mutating the HeaderList.
- Check writability before writing if unsure: if the list is from a response, treat it as read-only.
Example fix
// before (post-response script)
res.headerList.add('X-Custom', 'value'); // throws - response headers are read-only
// after (pre-request script)
req.headerList.add('X-Custom', 'value'); // correct - request headers are writable Defensive patterns
Strategy: validation
Validate before calling
// Check if you are working with request or response headers
// Response header lists are read-only; request header lists are writable.
// In scripts, always write to req.headerList, never res.headerList.
// No runtime API exposes the writable flag; the rule is: response = read-only.
if (source === 'request') {
req.headerList.add('X-Custom', 'value'); // safe
} else {
// copy response headers to a plain object for inspection instead
const headersCopy = { ...res.headerList.toObject() };
} Try / catch
try {
headerList.add(key, value);
} catch (e) {
if (e.message.includes('read-only')) {
console.error('Cannot modify response headers; they are immutable snapshots');
}
} Prevention
- Never call write methods on res.headerList; response headers are read-only snapshots.
- Only modify request headers via req.headerList or req.setHeader() in pre-request scripts.
- Copy response headers to a plain object if you need to transform them for assertions.
When it happens
Trigger: Calling res.getHeaderList().add('X-Custom', 'value') or any write method on res.headers / res.headerList. The HeaderList for responses is constructed with writable=false at header-list.js:118, so add/upsert/remove/clear all invoke #assertWritable and throw.
Common situations: Confusing request headers (writable) with response headers (read-only) and trying to modify the response header list. Attempting to set a header on the response in a post-response script. Using the same code path for req and res header lists without checking writability.
Related errors
- Workspace path not found
- Invalid Git URL
- Invalid environment: expected an object
- Invalid environment: missing or invalid variables array
- Invalid variable at index ${index}: expected an object
AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13).
Data as JSON: /api/errors/73adb9ca7875d170.
Report an issue: GitHub.