{"record":{"id":"8e828d204bd1e78f","repo":"ruvnet/RuView","slug":"guidance-reporoot-must-be-a-string-or-null","errorCode":null,"errorMessage":"guidance repoRoot must be a string or null","messagePattern":"guidance repoRoot must be a string or null","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"harness/homecore/src/guidance.js","lineNumber":69,"sourceCode":"\nexport function getGuidance(input = {}, options = {}) {\n  if (!input || typeof input !== 'object' || Array.isArray(input)) {\n    throw new TypeError('guidance input must be an object');\n  }\n  if (!options || typeof options !== 'object' || Array.isArray(options)) {\n    throw new TypeError('guidance options must be an object');\n  }\n  if (input.topic !== undefined && typeof input.topic !== 'string') {\n    throw new TypeError('guidance topic must be a string');\n  }\n  if (input.query !== undefined && typeof input.query !== 'string') {\n    throw new TypeError('guidance query must be a string');\n  }\n  if (input.limit !== undefined && (typeof input.limit !== 'number' || !Number.isFinite(input.limit))) {\n    throw new TypeError('guidance limit must be a finite number');\n  }\n  if (options.repoRoot !== undefined && options.repoRoot !== null && typeof options.repoRoot !== 'string') {\n    throw new TypeError('guidance repoRoot must be a string or null');\n  }\n\n  const topic = input.topic === undefined ? 'overview' : input.topic;\n  if (!GUIDANCE_TOPICS.includes(topic)) {\n    throw new RangeError(`unsupported guidance topic: ${topic}`);\n  }\n  const query = input.query === undefined ? '' : input.query.trim();\n  if (query && (query.length < 2 || query.length > 500)) {\n    throw new RangeError('guidance query must contain 2..500 characters');\n  }\n  const rawLimit = input.limit === undefined ? 20 : input.limit;\n  if (rawLimit < 1 || rawLimit > 20) {\n    throw new RangeError('guidance limit must be between 1 and 20');\n  }\n  const limit = Math.floor(rawLimit);\n  const wanted = tokenize(query);\n\n  const candidates = CAPABILITIES","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/harness/homecore/src/guidance.js#L51-L87","documentation":"refresh_token (auth.py:363) raises this when verify_token succeeds but get_user(sub) returns None or the user record has is_active falsy. The refresh flow re-validates the user on every refresh, so a valid-but-orphaned or deactivated token cannot be exchanged for a new one.","triggerScenarios":"Calling refresh_token with a token whose user was created before a server restart (in-memory store now empty); user deactivated between issuance and refresh; sub claim is a username never registered on this instance.","commonSituations":"Long-running clients attempting silent refresh after a backend restart; deployments where refresh is expected to survive user-store resets; multi-instance setups with per-process user dicts.","solutions":["Fall back to full login (username/password) to obtain a brand-new token","Ensure the user exists and is_active=True in this process before refreshing","Persist the user store so restarts do not orphan live tokens"],"exampleFix":"# before\ntokens = await auth.refresh_token(old_token)\n# after\ntry:\n    tokens = await auth.refresh_token(old_token)\nexcept AuthenticationError:\n    tokens = await auth.login(username, password)  # full re-auth","handlingStrategy":"fallback","validationCode":"def refresh_will_succeed(token_manager, user_manager, token: str) -> bool:\n    \"\"\"refresh_token re-checks user existence and is_active.\"\"\"\n    claims = token_manager.decode_token_claims(token)\n    if claims is None:\n        return False\n    user = user_manager.get_user(claims.get(\"sub\", \"\"))\n    return user is not None and bool(user.get(\"is_active\", False))","typeGuard":null,"tryCatchPattern":"try:\n    tokens = await middleware.refresh_token(token)\nexcept AuthenticationError:\n    # covers 'User not found or inactive' and the masked generic case\n    tokens = await middleware.login(username, password)  # fallback re-auth","preventionTips":["Chain refresh -> login fallback in every client","Refresh before expiry to avoid the inactive-user edge at the wire","Keep the user store persistent so refresh survives restarts"],"tags":["auth","jwt","refresh-token"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}