nextauthjs/next-auth · error
Object is nullish
Error message
Object is nullish
What it means
The Hasura adapter's format.from mapper converts Hasura rows into Auth.js user/session objects. Callers like createUser/getUser pass throwIfNullish when a null result is unacceptable, and format.from then throws 'Object is nullish' instead of returning null. It fires whenever the input object is undefined, null, or otherwise falsy and the caller demanded a non-null result.
Source
Thrown at packages/adapter-hasura/src/index.ts:183
DeleteVerificationTokenDocument,
params
)
const verificationToken = delete_verification_tokens?.returning?.[0]
return format.from(
useFragment(VerificationTokenFragmentDoc, verificationToken)
)
},
}
}
export const format = {
from<T, B extends boolean = false>(
object?: Record<string, any> | null | undefined,
throwIfNullish?: B
): B extends true ? T : T | null {
if (!object) {
if (throwIfNullish) throw new Error("Object is nullish")
return null as any
}
const newObject: Record<string, unknown> = {}
for (const [key, value] of Object.entries(object))
newObject[key] = isDate(value) ? new Date(value) : value
return newObject as T
},
to<T>(object: Record<string, any>): T {
const newObject: Record<string, unknown> = {}
for (const [key, value] of Object.entries(object))
newObject[key] = value instanceof Date ? value.toISOString() : value
return newObject as T
},View on GitHub (pinned to a1a16a5a77)
Solutions
- Confirm the record exists in Hasura before calling the adapter, or handle the throw in try/catch
- Verify the adapter's table and field mappings match the actual Hasura schema
- Check the Hasura endpoint/role permissions allow the query to see the row (row-level permissions can filter it out)
- Clear stale auth cookies referencing deleted users
Example fix
// before
const user = await adapter.getUserByEmail(email) // throws if missing
// after
let user = null
try {
user = await adapter.getUserByEmail(email)
} catch {
user = null
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!email) throw new Error('email required before getUserByEmail') Type guard
function isRow(v: unknown): v is Record<string, unknown> {
return v !== null && typeof v === 'object'
} Try / catch
try {
user = await adapter.getUserByEmail(email)
} catch (e) {
if ((e as Error).message === 'Object is nullish') user = null
else throw e
} Prevention
- Validate lookup keys (id/email) before calling the adapter
- Handle 'user may not exist' flows explicitly
- Verify Hasura table/field mappings after schema changes
- Check Hasura role permissions allow selecting the row
When it happens
Trigger: Calling getUser/getUserByEmail/getUserByAccount with an id/email/provider-account that has no matching Hasura row, deleteUser/updateUser on a nonexistent record, or Hasura returning no rows due to wrong table/field mapping in the adapter config.
Common situations: Typo'd email lookup, stale cookie referencing a deleted user, Hasura GraphQL query returning errors mapped to undefined, adapter table/column mapping misconfigured so queries always return empty.
Related errors
- User not found
- User not created
- Error creating user: Cannot get user after creation.
- Error updating user: Cannot get user after updating.
- Error updating user: Failed to run the update SQL.
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/c75d08772a42e149.
Report an issue: GitHub.