hcengineering/platform · error
Failed to ensure person exists for email: ${email}
Error message
Failed to ensure person exists for email: ${email} What it means
ensurePerson resolves (or creates and caches) a Person record for an email address. If the cached/returned promise resolves to undefined — the fetch-and-cache path found or produced no person — this Error is thrown because subsequent mail processing requires a concrete Person (socialId).
Source
Thrown at services/mail/mail-common/src/person.ts:55
private readonly restClient: RestClient
) {}
/**
* Gets or creates a person by email address with caching
*/
async ensurePerson (contact: EmailContact): Promise<CachedPerson> {
const email = contact.email.toLowerCase().trim()
let personPromise = this.cache.get(email)
if (personPromise === undefined) {
personPromise = this.fetchAndCachePerson(email, contact.firstName, contact.lastName)
this.cache.set(email, personPromise)
}
const result = await personPromise
if (result === undefined) {
throw new Error(`Failed to ensure person exists for email: ${email}`)
}
this.emailCache.set(result.socialId, email)
return result
}
async getEmailBySocialId (socialId: PersonId): Promise<string | undefined> {
return this.emailCache.get(socialId)
}
size (): number {
return this.cache.size
}
clearCache (): void {
this.cache.clear()
this.emailCache.clear()
}
View on GitHub (pinned to 63e28dc964)
Solutions
- Inspect why fetchAndCachePerson returned undefined — check DB errors and whether person creation is permitted in the workspace.
- Validate the email is non-empty and well-formed before calling ensurePerson (see also 'Invalid email address').
- Catch the error and skip/queue the message for retry instead of failing the whole ingestion pipeline.
- Check for creation races; make fetchAndCachePerson's upsert idempotent and always return the person.
Example fix
// before
const person = await service.ensurePerson(ctx, email) // throws if undefined
// after
if (!email || !email.includes('@')) {
throw new Error(`Skipping message: bad sender email "${email}"`)
}
const person = await service.ensurePerson(ctx, email) Defensive patterns
Strategy: try-catch
Validate before calling
if (typeof email !== 'string' || !email.includes('@')) {
throw new Error(`ensurePerson requires a valid email, got: ${email}`)
} Type guard
function isValidEmail(email: string): boolean {
return /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)
} Try / catch
try {
person = await service.ensurePerson(ctx, email)
} catch (err) {
if (err.message.startsWith('Failed to ensure person exists')) {
console.warn(`Skipping message from unresolvable person: ${email}`)
return // or queue for retry
}
throw err
} Prevention
- Validate sender/recipient emails before message processing.
- Monitor person creation failures — they usually indicate DB or permission problems.
- Handle empty/placeholder addresses ('undisclosed-recipients') before calling ensurePerson.
When it happens
Trigger: fetchAndCachePerson returning undefined for the email (creation failed silently or lookup returned nothing) while processing message sender/recipient (fromPerson/toPerson) records.
Common situations: Emails from malformed or empty addresses slipping through upstream validation; concurrent processing racing person creation so one path resolves nothing; database issue during person upsert; contact with blank firstName/lastName plus a lookup-only path.
Related errors
- Failed to load server config
- getDisplayMedia not supported
- No screen access granted
- Failed to create channel for ${normalizedEmail} in space ${s
- Invalid email address
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/c2cb37716a323421.
Report an issue: GitHub.