sickn33/agentic-awesome-skills · error · Error

User ${userId} not found

Error message

User ${userId} not found

What it means

In fp-refactor's OO example, UserService.updateEmail throws (and logs) this when userRepo.findById resolves falsy for the given userId. It is a business-layer not-found guard before mutating the user entity.

Source

Thrown at skills/fp-refactor/SKILL.md:682

interface EmailService {
  send(to: string, subject: string, body: string): Promise<void>;
}

class UserService {
  constructor(
    private readonly logger: Logger,
    private readonly userRepo: UserRepository,
    private readonly emailService: EmailService
  ) {}

  async updateEmail(userId: string, newEmail: string): Promise<void> {
    this.logger.log(`Updating email for user ${userId}`);

    const user = await this.userRepo.findById(userId);
    if (!user) {
      this.logger.error(`User ${userId} not found`);
      throw new Error(`User ${userId} not found`);
    }

    const oldEmail = user.email;
    user.email = newEmail;

    await this.userRepo.save(user);

    await this.emailService.send(
      oldEmail,
      'Email Changed',
      `Your email has been changed to ${newEmail}`
    );

    this.logger.log(`Email updated for user ${userId}`);
  }
}

// Manual DI setup

View on GitHub (pinned to 58d857988f)

Solutions

  1. Verify the user still exists before showing the edit form (or refresh on save)
  2. Map this throw to a 404 response at the controller boundary instead of a 500
  3. Return TaskEither<DomainError, void> with a UserNotFound tagged error per the skill's refactor

Example fix

// before
const user = await this.userRepo.findById(userId)
if (!user) throw new Error(`User ${userId} not found`)

// after: tagged, typed failure
type DomainError = { _tag: 'UserNotFound'; userId: string } | { _tag: 'RepoError'; cause: Error }
const user = await this.userRepo.findById(userId)
if (!user) return E.left<DomainError, void>({ _tag: 'UserNotFound', userId })
Defensive patterns

Strategy: try-catch

Validate before calling

// before showing an edit form:
const exists = await userRepo.findById(userId)
if (!exists) throw new Response('User not found', { status: 404 })

Try / catch

try {
  await userService.updateEmail(userId, email)
} catch (e) {
  if (e instanceof Error && /not found/.test(e.message)) {
    return res.status(404).json({ error: 'User not found' })
  }
  throw e
}

Prevention

When it happens

Trigger: Calling updateEmail with a deleted user's id, a wrong-environment id, or an id race where the user is removed between screen load and save.

Common situations: Admin dashboards editing archived users; stale SPA state after another admin deletes the account; repository returning null for soft-deleted rows while the UI still lists them.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of sickn33/agentic-awesome-skills@58d857988f (2026-08-26). Data as JSON: /api/errors/686b1c665e322f57. Report an issue: GitHub.