{"record":{"id":"df54b2bdcb5906ae","repo":"moeru-ai/airi","slug":"username-is-empty-please-provide-a-username-to-re","errorCode":null,"errorMessage":"Username is empty. Please provide a username to retrieve.","messagePattern":"Username is empty\\. Please provide a username to retrieve\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"integrations/twitter-services/src/adapters/airi-adapter.ts","lineNumber":200,"sourceCode":"  private async handleGetUser(content: string): Promise<boolean> {\n    if (content) {\n      const userProfile = await this.twitterServices.user.getUserProfile(content)\n      logger.main.log(`Retrieved profile for user: @${content}`)\n      // Return user info to the user\n      this.client.send({\n        type: 'input:text',\n        data: {\n          text: `User Profile for @${userProfile.username}:\nDisplay Name: ${userProfile.displayName}\nBio: ${userProfile.bio || 'N/A'}\nFollowers: ${userProfile.followersCount || 0}\nFollowing: ${userProfile.followingCount || 0}`,\n        },\n      })\n      return true\n    }\n    else {\n      throw new Error('Username is empty. Please provide a username to retrieve.')\n    }\n  }\n\n  private async handleGetTimeline(count: number): Promise<boolean> {\n    const timelineOptions = { count }\n    const tweets = await this.twitterServices.timeline.getTimeline(timelineOptions)\n    logger.main.log(`Retrieved ${tweets.length} tweets from timeline`)\n    // Return timeline to the user\n    this.client.send({\n      type: 'input:text',\n      data: {\n        text: `Latest ${tweets.length} tweets from your timeline:\n${tweets.map((t: Tweet) => `- ${t.author.displayName}: ${t.text.substring(0, 80)}...`).join('\\n')}`,\n      },\n    })\n    return true\n  }\n","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/integrations/twitter-services/src/adapters/airi-adapter.ts#L182-L218","documentation":"Thrown by handleGetUser when the parsed command's content is falsy — i.e. 'get user:' was sent with no username. This is a plain Error raised before getUserProfile is called, so no profile lookup occurs.","triggerScenarios":"User sends 'get user:' with nothing after the colon; parseTwitterCommand matched the 'get user' prefix but content is empty/whitespace.","commonSituations":"User forgot to type the @handle; LLM truncated the payload; empty input forwarded by the AIRI input:text event.","solutions":["Provide a non-empty username after 'get user:'.","Validate content in the parser and reprompt for the username before dispatch.","Have the adapter reply with usage guidance instead of throwing."],"exampleFix":"// before\nif (content) { /* fetch profile */ } else {\n  throw new Error('Username is empty. Please provide a username to retrieve.')\n}\n\n// after\nconst user = content?.trim()\nif (!user) {\n  this.client.send({ type: 'input:text', data: { text: 'Usage: get user: <username>' } })\n  return false\n}","handlingStrategy":"validation","validationCode":"const user = (content ?? '').trim()\nif (!user) {\n  throw new Error('Username required')\n}\nawait adapter.handleGetUser(user)","typeGuard":"function isEmptyUsernameError(e: unknown): boolean {\n  return e instanceof Error && /Username is empty/.test(e.message)\n}","tryCatchPattern":"try {\n  await this.handleGetUser(content)\n} catch (e) {\n  if (e instanceof Error && /Username is empty/.test(e.message)) {\n    this.client.send({ type: 'input:text', data: { text: 'Usage: get user: <username>' } })\n  } else throw e\n}","preventionTips":["Validate parsed content for the 'get user' command before dispatch.","Always include the @handle after the prefix.","Reply with usage hints instead of throwing on empty input."],"tags":["twitter","validation","user","adapter","empty-input"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}