ruvnet/RuView · error · TypeError
guidance query must be a string
Error message
guidance query must be a string
What it means
Raised by AuthenticationMiddleware.login (auth.py:305) when UserManager.authenticate_user returns None. That happens for three distinct causes that are deliberately indistinguishable to callers: unknown username, bcrypt password verification failure, or the user being inactive (is_active falsy).
Source
Thrown at harness/homecore/src/guidance.js:63
return [...new Set(values)];
}
export function listGuidanceTopics() {
return GUIDANCE_TOPICS.map((topic) => ({ topic, summary: TOPIC_SUMMARIES[topic] }));
}
export function getGuidance(input = {}, options = {}) {
if (!input || typeof input !== 'object' || Array.isArray(input)) {
throw new TypeError('guidance input must be an object');
}
if (!options || typeof options !== 'object' || Array.isArray(options)) {
throw new TypeError('guidance options must be an object');
}
if (input.topic !== undefined && typeof input.topic !== 'string') {
throw new TypeError('guidance topic must be a string');
}
if (input.query !== undefined && typeof input.query !== 'string') {
throw new TypeError('guidance query must be a string');
}
if (input.limit !== undefined && (typeof input.limit !== 'number' || !Number.isFinite(input.limit))) {
throw new TypeError('guidance limit must be a finite number');
}
if (options.repoRoot !== undefined && options.repoRoot !== null && typeof options.repoRoot !== 'string') {
throw new TypeError('guidance repoRoot must be a string or null');
}
const topic = input.topic === undefined ? 'overview' : input.topic;
if (!GUIDANCE_TOPICS.includes(topic)) {
throw new RangeError(`unsupported guidance topic: ${topic}`);
}
const query = input.query === undefined ? '' : input.query.trim();
if (query && (query.length < 2 || query.length > 500)) {
throw new RangeError('guidance query must contain 2..500 characters');
}
const rawLimit = input.limit === undefined ? 20 : input.limit;
if (rawLimit < 1 || rawLimit > 20) {View on GitHub (pinned to 4685618388)
Solutions
- Confirm the user exists in this process: user_manager.get_user(name) is not None
- Re-register the user if the store was wiped by a restart
- Verify the password matches the one used at create_user and check is_active is True
- Strip whitespace from form inputs before submitting
Example fix
# before
resp = await middleware.login("alice", "hunter2")
# after
if user_manager.get_user("alice") is None:
user_manager.create_user("alice", "a@b.c", "hunter2")
resp = await middleware.login("alice", "hunter2") Defensive patterns
Strategy: try-catch
Validate before calling
def login_should_succeed(user_manager, username: str, password: str) -> bool:
"""Mirrors authenticate_user's three checks without calling login()."""
user = user_manager.get_user(username)
if user is None:
return False
from src.middleware.auth import pwd_context
return pwd_context.verify(password, user["hashed_password"]) and bool(user.get("is_active", False)) Try / catch
from src.middleware.auth import AuthenticationError
try:
result = await middleware.login(username, password)
except AuthenticationError as e:
if str(e) == "Invalid username or password":
# unknown user, wrong password, or inactive -- all identical by design
raise HTTPException(401, "Invalid username or password")
raise Prevention
- Register users before login tests; remember restarts wipe the store
- Keep the identical-message behavior - do not leak which factor failed
- Strip inputs client-side to avoid phantom whitespace failures
When it happens
Trigger: POST login with a username not in self._users (fresh process, never registered); wrong password; user exists with correct password but is_active=False; typo'd or URL-encoded credentials.
Common situations: Server restarted and in-memory users vanished, so every login fails with this message; user registered on a different instance; password changed elsewhere; copy-paste including whitespace in username/password.
Related errors
- brain line ${index + 1}: exceeds 16 KiB
- brain line ${index + 1}: ${error.message}
- brain line ${index + 1}: ${errors.join('; ')}
- brain corpus exceeds 1000 records
- duplicate brain id: ${record.id}
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/90a8145e8463eb67.
Report an issue: GitHub.