xai-org/x-algorithm · error · ConfigFailure

Conflict config name:${nameSeq.mkString}

Error message

Conflict config name:${nameSeq.mkString}

What it means

BotMaker's ServiceConfigs keeps a global registry of unique config name sequences. The unique(names...) helper throws ConfigFailure when the same name sequence (e.g. an eventType, or eventType+endpoint pair) is registered twice, preventing ambiguous duplicate bot/event/endpoint definitions.

Source

Thrown at botmaker/src/scala/com/twitter/botmaker/runtime/config/ServiceConfigs.scala:49

abstract class ServiceConfigs extends ConfigContainer with Debuggable {

  private final val container = mutable.Map[String, (Type, String, AnyRef)]()
  private final val uniqueNames = mutable.Set[Seq[Any]]()
  private final val thriftTypeConfigs = mutable.Map[String, ThriftTypeConfig]()
  private final val structTupleTypeConfigs = mutable.Map[String, StructTupleTypeConfig]()

  val eventTypeRegex: Regex = "^[a-z][a-z0-9_]*$".r
  val fieldNameRegex: Regex = "^[a-zA-Z_][a-zA-Z0-9_]*$".r
  val funcNameRegex: Regex = "^[A-Z][a-zA-Z0-9_]*$".r
  val endpointRegex: Regex = "^[a-z][a-zA-Z0-9_]*$".r
  val datasetRegex: Regex = "^[a-zA-Z_][a-zA-Z0-9_]*$".r
  val typeNameRegex: Regex = "^[A-Z][a-zA-Z0-9_]*$".r
  val teamNameRegex: Regex = "^[a-z][a-z0-9\\-]*$".r

  def unique(names: Any*): Unit = synchronized {
    val nameSeq = names.toSeq
    if (uniqueNames.contains(nameSeq)) {
      throw ConfigFailure(
        s"Conflict config name:${nameSeq.mkString}"
      )
    }
    uniqueNames += nameSeq
  }

  def validate(condition: Boolean, err: String): Unit = {
    if (!condition) {
      throw ConfigFailure(err)
    }
  }

  def validateEventType(eventType: String): Unit = {
    if (eventTypeRegex.findFirstIn(eventType).isEmpty) {
      throw ConfigFailure(
        s"Event type '$eventType' does not match $eventTypeRegex."
      )
    }

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Rename one of the conflicting configs so the name sequence is unique (the message concatenates the names, so parse it to find the duplicate)
  2. If registering from a shared trait, parameterize the eventType so each service injects its own name
  3. In tests, reset/clear the ServiceConfigs uniqueNames registry between test cases

Example fix

// before
addScheduledEvent(ScheduledEventConfig(eventType = "ContentScan", ...))
addScheduledEvent(ScheduledEventConfig(eventType = "ContentScan", ...)) // duplicate

// after
addScheduledEvent(ScheduledEventConfig(eventType = "ContentScan", ...))
addScheduledEvent(ScheduledEventConfig(eventType = "ContentScanNightly", ...))
Defensive patterns

Strategy: validation

Validate before calling

seen = set()
def register(name_seq):
    key = tuple(name_seq)
    if key in seen: raise ValueError(f"duplicate config name {key}")
    seen.add(key); unique(*name_seq)

Try / catch

try:
    addScheduledEvent(cfg)
except ConfigFailure as e:
    if str(e).startswith("Conflict config name:"):
        cfg = cfg.copy(eventType=cfg.eventType + "2"); addScheduledEvent(cfg)
    else:
        raise

Prevention

When it happens

Trigger: Registering two events, endpoints, or configs with the same eventType; or two configs sharing the same (eventType, endpoint) pair — e.g. calling addScheduledEvent twice with the same config.eventType.

Common situations: Copy-pasting a config block and forgetting to rename the eventType; a shared config trait mixed into two services registering the same names; redeploying/re-registering configs within the same JVM in tests without resetting ServiceConfigs.

Related errors


AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28). Data as JSON: /api/errors/1d8351547b3e7bb1. Report an issue: GitHub.