remix-run/remix · error · Error

Cannot install context property {formattedProperty} because

Error message

Cannot install context property {formattedProperty} because this context key already uses {JSON.stringify(existingProperty)}.

What it means

Each context key object can only be associated with one property name. This error fires when you call ctx.set with the same key object but a different property name than a previous call in the same process/context.

Source

Thrown at packages/fetch-router/src/lib/request-context.ts:307

    }

    this.#contextMap.set(key, value)
  }

  #installContextProperty(key: object, property: string): void {
    if (typeof property !== 'string') {
      throw new Error('Context property name must be a string.')
    }

    if (property.length === 0) {
      throw new Error('Cannot install an empty context property name.')
    }

    let formattedProperty = JSON.stringify(property)

    let existingProperty = this.#contextPropertyKeys.get(key)
    if (existingProperty != null && existingProperty !== property) {
      throw new Error(
        `Cannot install context property ${formattedProperty} because this context key already uses ${JSON.stringify(existingProperty)}.`,
      )
    }

    let existingKey = this.#contextProperties.get(property)
    if (existingKey != null) {
      if (existingKey !== key) {
        throw new Error(
          `Cannot install context property ${formattedProperty} because another context key already uses it.`,
        )
      }

      return
    }

    if (property in this) {
      throw new Error(
        `Cannot install context property ${formattedProperty} because it already exists on RequestContext.`,

View on GitHub (pinned to 9696913134)

Solutions

  1. Use one property name per context key consistently across the app
  2. Export the key and its property name as a pair from a single module
  3. Rename all call sites together when changing a property name

Example fix

// before
// a.ts
ctx.set(sessionKey, s, { property: 'session' })
// b.ts
ctx.set(sessionKey, s, { property: 'auth' })
// after
// context/session.ts
export const sessionProperty = 'session'
// both files use { property: sessionProperty }
Defensive patterns

Strategy: validation

Validate before calling

const existing = contextPropertyKeys.get(key)
if (existing != null && existing !== property) throw new Error('key/property mismatch')

Prevention

When it happens

Trigger: Two middleware files both do ctx.set(sessionKey, x, { property: 'session' }) and later ctx.set(sessionKey, y, { property: 'auth' }) using the same imported key symbol.

Common situations: Copy-pasting middleware and renaming the property; refactoring that changes the property string while the shared key module still exports the old usage.

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/7db142e43948d7fa. Report an issue: GitHub.