remix-run/remix · error · Error

Context property name must be a string.

Error message

Context property name must be a string.

What it means

RequestContext lets middleware attach named properties via set(key, value, { property }). The property name must be a string so it can be installed on the context object; this error fires when the property option is a symbol, number, or other non-string value.

Source

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

   * @param key The key to write
   * @param value The value to write
   * @param options Options for installing the value as a direct context property
   */
  set = <key extends object>(
    key: key,
    value: ContextValue<key>,
    options?: { property: string },
  ): void => {
    if (options != null) {
      this.#installContextProperty(key, options.property)
    }

    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) {

View on GitHub (pinned to 9696913134)

Solutions

  1. Coerce or validate the property name to a non-empty string before calling set
  2. Use static string literals for property names where possible
  3. Validate dynamic config keys with typeof checks before registering

Example fix

// before
ctx.set(key, value, { property: config.name })
// after
ctx.set(key, value, { property: String(config.name) })
Defensive patterns

Strategy: validation

Validate before calling

if (typeof property !== 'string' || property.length === 0) throw new TypeError('invalid property name')

Type guard

const isValidPropertyName = (v: unknown): v is string => typeof v === 'string' && v.length > 0

Prevention

When it happens

Trigger: ctx.set(key, value, { property: someSymbol }) or passing a numeric/undefined property option at runtime (e.g. from dynamic config).

Common situations: Programmatically deriving property names from data that isn't guaranteed to be a string; TS types not covering a JS call site.

Related errors


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