ruvnet/RuView · error · Error
brain line ${index + 1}: ${error.message}
Error message
brain line ${index + 1}: ${error.message} What it means
_authenticate_request (auth.py:249) raises AuthenticationError('Missing authorization header') when the request carries no Authorization header at all AND _requires_auth() is true, i.e. the path starts with /api/ or /ws/. Requests to other paths without a header pass through unauthenticated.
Source
Thrown at harness/homecore/src/brain.js:82
if (canonical && record.reviewed !== true) errors.push('canonical records must be reviewed');
const combined = `${record.title || ''}\n${record.content || ''}`;
if (SECRET.test(combined)) errors.push('record appears to contain a secret');
if (INJECTION.test(combined)) errors.push('record contains instruction-like prompt injection');
return errors;
}
export function loadBrain(path = CORPUS_PATH) {
const raw = readFileSync(path, 'utf8').replace(/\r\n/g, '\n');
if (Buffer.byteLength(raw) > 1_048_576) throw new Error('brain corpus exceeds 1 MiB');
const records = raw.split('\n').filter(Boolean).map((line, index) => {
if (Buffer.byteLength(line) > 16_384) {
throw new Error(`brain line ${index + 1}: exceeds 16 KiB`);
}
let record;
try {
record = JSON.parse(line);
} catch (error) {
throw new Error(`brain line ${index + 1}: ${error.message}`);
}
const errors = validateBrainRecord(record, { canonical: true });
if (errors.length) throw new Error(`brain line ${index + 1}: ${errors.join('; ')}`);
return Object.freeze(record);
});
if (records.length > 1000) throw new Error('brain corpus exceeds 1000 records');
const ids = new Set();
for (const record of records) {
if (ids.has(record.id)) throw new Error(`duplicate brain id: ${record.id}`);
ids.add(record.id);
}
return { records, digest: sha256(raw), bytes: Buffer.byteLength(raw) };
}
function terms(value) {
return new Set(String(value).toLowerCase().match(/[a-z0-9][a-z0-9_-]{1,}/g) || []);
}
View on GitHub (pinned to 4685618388)
Solutions
- Send the header: Authorization: Bearer <access_token> obtained from the login endpoint
- If the header is sent but still missing server-side, check reverse-proxy/CORS config for header stripping
- Confirm the endpoint really requires auth - only /api/* and /ws/* prefixes do
Example fix
# before
resp = requests.get("http://host/api/users")
# after
resp = requests.get("http://host/api/users", headers={"Authorization": f"Bearer {token}"}) Defensive patterns
Strategy: validation
Validate before calling
def protected_call_ready(path: str, headers: dict) -> bool:
"""Paths under /api/ or /ws/ need an Authorization header."""
needs_auth = path.startswith("/api/") or path.startswith("/ws/")
return (not needs_auth) or bool(headers.get("Authorization")) Type guard
def has_bearer_header(headers: dict) -> bool:
return isinstance(headers.get("Authorization"), str) and bool(headers["Authorization"].strip()) Try / catch
from src.middleware.auth import AuthenticationError
try:
user = await middleware._authenticate_request(request)
except AuthenticationError as e:
if str(e) == "Missing authorization header":
return PlainTextResponse("Bearer token required", status_code=401,
headers={"WWW-Authenticate": "Bearer"})
raise Prevention
- Centralize header attachment in one HTTP client wrapper
- Verify proxies forward the Authorization header
- Login before any /api/* call in scripts and tests
When it happens
Trigger: curl http://host/api/anything with no -H 'Authorization: ...'; a WebSocket client connecting to /ws/feed without a token in the header; a frontend that stores the token in a variable but forgets to attach it to fetch/axios calls; browser preflight/introspection calls that strip headers.
Common situations: Client not yet logged in but already calling protected endpoints; proxy (nginx) or CORS configuration stripping the Authorization header; token attach code conditioned on a flag that is false; curl scripts missing the header.
Related errors
- brain line ${index + 1}: exceeds 16 KiB
- brain line ${index + 1}: ${errors.join('; ')}
- brain corpus exceeds 1000 records
- guidance query must contain 2..500 characters
- prompt must be a non-empty string
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/2eabcc71d374ce3f.
Report an issue: GitHub.