{"record":{"id":"f8575c08f2a16b42","repo":"t8y2/dbx","slug":"the-default-exchange-cannot-be-deleted","errorCode":null,"errorMessage":"The default exchange cannot be deleted","messagePattern":"The default exchange cannot be deleted","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/rabbitmq/operations.go","lineNumber":484,"sourceCode":"\nfunc exchangeName(params jsonObject) (string, error) {\n\tname := stringOrEmpty(params, \"name\")\n\tif strings.TrimSpace(name) == \"\" {\n\t\treturn \"\", errors.New(\"name is required\")\n\t}\n\treturn name, nil\n}\n\nfunc validateExchangeType(exchangeType string) (string, error) {\n\tif _, ok := exchangeTypes[exchangeType]; !ok {\n\t\treturn \"\", fmt.Errorf(\"Invalid exchange type '%s'. Supported types: direct, fanout, topic, headers\", exchangeType)\n\t}\n\treturn exchangeType, nil\n}\n\nfunc assertExchangeDeletable(name string) error {\n\tif name == \"\" {\n\t\treturn errors.New(\"The default exchange cannot be deleted\")\n\t}\n\tif strings.HasPrefix(name, \"amq.\") {\n\t\treturn fmt.Errorf(\"The built-in exchange '%s' cannot be deleted\", name)\n\t}\n\treturn nil\n}\n\nfunc (s *server) listBindings(params jsonObject) (any, error) {\n\tconnection, err := s.requireConnectionConfig(params)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tallVhosts := allVhostsRequested(params)\n\tbindings, err := managementGetAll(connection, managementListPath(params, connection, \"bindings\"))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\texchangeFilter := stringOrEmpty(params, \"exchange\")","sourceCodeStart":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/rabbitmq/operations.go#L466-L502","documentation":"assertExchangeDeletable() implements a semantic guard in deleteExchange that refuses to delete the default exchange. The default exchange (\"\" empty string) is a built-in RabbitMQ construct that cannot and should not be removed, so the library blocks the operation up front. A second guard in the same function blocks 'amq.*' built-in exchanges with a different message.","triggerScenarios":"Calling deleteExchange with name set to \"\" (the empty string denotes the default exchange in AMQP). Note the guard checks name == \"\" exactly, so a whitespace-only name would NOT be caught here.","commonSituations":"Bulk cleanup scripts that iterate over a list of exchange names where one entry is empty; config where the exchange name defaults to \"\" when unset; attempting to 'reset' a vhost by deleting all exchanges including the implicit default one.","solutions":["Remove the default exchange (empty name) from your deletion list — it is built-in and cannot be deleted.","Filter out empty and 'amq.'-prefixed exchange names before calling deleteExchange.","If the intent is to unbind a queue from the default exchange, call unbind instead of deleteExchange."],"exampleFix":"// before\nfor _, name := range exchangeNames {\n    deleteExchange(jsonObject{\"name\": name}) // fails on \"\"\n}\n// after\nfor _, name := range exchangeNames {\n    if name == \"\" || strings.HasPrefix(name, \"amq.\") {\n        continue\n    }\n    deleteExchange(jsonObject{\"name\": name})\n}","handlingStrategy":"validation","validationCode":"if name == \"\" || strings.HasPrefix(name, \"amq.\") {\n    return errors.New(\"refusing to delete built-in exchange: \" + name)\n}\ndeleteExchange(jsonObject{\"name\": name})","typeGuard":"func isDeletableExchange(name string) bool {\n    return name != \"\" && !strings.HasPrefix(name, \"amq.\")\n}","tryCatchPattern":null,"preventionTips":["Never include the default (empty-name) exchange or amq.* exchanges in cleanup lists.","Filter exchange listings before batch deletion rather than relying on the server to reject them.","Remember the default exchange is identified by the empty string, not a literal name."],"tags":["rabbitmq","protected-resource","semantic-guard","delete"],"backgroundTag":"protected-resource-modification","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}