hcengineering/platform · error

Duplicated storage name ${config.name}, skipping config:${st

Error message

Duplicated storage name ${config.name}, skipping config:${st}

What it means

While parsing STORAGE_CONFIG, each entry's name defaults to its kind, and entries are pushed into storageConfig.storages which must have unique names. If an entry's computed name already exists, parseStorageEnv throws Error('Duplicated storage name <name>, skipping config:<st>'). Duplicate symbolic names would make the fallback/target lookup ambiguous, so it's treated as a hard config error.

Source

Thrown at foundations/server/packages/server-storage/src/starter.ts:73

      // No protocol, add empty one
      url = 'empty://' + url
      hasProtocol = false
    }
    const uri = new URL(url)
    const config: StorageConfig = {
      kind,
      name,
      endpoint: (hasProtocol ? uri.protocol + '//' : '') + uri.hostname, // Port should go away
      port: uri.port !== '' ? parseInt(uri.port) : undefined
    }

    // Add all extra parameters
    uri.searchParams.forEach((v, k) => {
      ;(config as any)[k] = v
    })

    if (storageConfig.storages.find((it) => it.name === config.name) !== undefined) {
      throw new Error(`Duplicated storage name ${config.name}, skipping config:${st}`)
    }
    storageConfig.storages.push(config)
    storageConfig.default = config.name
  }
}

export function createStorageFromConfig (config: StorageConfig): StorageAdapter {
  let adapter: StorageAdapter
  const kind = config.kind
  if (kind === MINIO_CONFIG_KIND) {
    const c = config as MinioConfig
    if (c.endpoint == null || c.accessKey == null || c.secretKey == null) {
      throw new Error('One of endpoint/accessKey/secretKey values are not specified')
    }
    adapter = new MinioService(c)
  } else if (kind === S3_CONFIG_KIND) {
    const c = config as S3Config
    if (c.endpoint == null || c.accessKey == null || c.secretKey == null) {

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Give each storage entry a unique explicit name: 'kind,uniquename|uri|contentTypes'
  2. If two entries of the same kind are intentional (e.g. minio + s3 fallback), rename one so the name component differs
  3. Search STORAGE_CONFIG for duplicated tokens before the '|' and fix the repeat
  4. Restart and confirm the server lists the expected number of storages

Example fix

// before
STORAGE_CONFIG=minio,primary|a:9000...;s3,primary|b...
// after
STORAGE_CONFIG=minio,primary|a:9000...;s3,backup|b...
Defensive patterns

Strategy: validation

Validate before calling

const names = (process.env.STORAGE_CONFIG ?? '').split(';').map(s => s.split('|')[0].split(',')[1] ?? s.split('|')[0].split(',')[0])
const dupes = names.filter((n, i) => names.indexOf(n) !== i)
if (dupes.length > 0) throw new Error(`Duplicate storage names: ${dupes.join(',')}`)

Type guard

function hasUniqueNames (entries: string[]): boolean {
  const names = entries.map(e => { const [kindName] = e.split('|'); const [kind, name] = kindName.split(','); return name ?? kind })
  return new Set(names).size === names.length
}

Try / catch

try {
  parseStorageEnv(storageEnv, storageConfig)
} catch (err) {
  if ((err as Error).message.startsWith('Duplicated storage name')) {
    console.error('Fix STORAGE_CONFIG: ', (err as Error).message)
    process.exit(1)
  }
  throw err
}

Prevention

When it happens

Trigger: Two ';'-separated STORAGE_CONFIG entries resolving to the same name — e.g. 'minio|minio:9000...;minio|other:9000...' (both default to name 'minio'), or an explicit name repeated like 'minio,primary|...;s3,primary|...'.

Common situations: Copy-pasting a storage entry to add a second bucket/endpoint but forgetting to change the explicit ,name part; same kind listed twice assuming names would auto-suffix; templating loops generating configs where the name variable didn't change per iteration.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/4081f4a02561f2e9. Report an issue: GitHub.