OpenKeel: the sovereign French Cloud solution of the inherent group, with a European reach Discover inherent

Reverse-spec · Services

placement — Errors

Error codes and messages — placement — branch stable/2026.2

Branch stable/2026.2 @ f4a89d3803cb — repository https://opendev.org/openstack/placement — analysed on 2026-10-28

Exception → HTTP translation

Placement has no central translation table: its exceptions (placement/exception.py) carry no HTTP status. Each handler catches business exceptions and raises a webob.exc.HTTP* itself, with a structured code passed in comment=errors.XXX. Three safety nets complete this mechanism:

LayerBehaviourWhere
PlacementHandlerany uncaught exception.NotFound yields 404; PolicyNotAuthorized yields 403placement/handler.py:219-229
PlacementWsgifytakes the comment of the HTTP exception and stores it in environ['placement.error_code']placement/wsgi_wrapper.py
MicroversionMiddlewareformats HTTP errors as JSON and adds the microversion headerplacement/deploy.py:58-60
FaultWrapperany other exception yields 500, with LOG.exception('Placement API unexpected error: …')placement/fault_wrap.py

The inventory's http_conversions section lists the 68 local conversions found in the handlers (_inventory/inventory_stable-2026.2.md).

Body format (placement/util.py, json_error_formatter):

{"errors": [{"status": 409,
             "title": "Conflict",
             "detail": "There was a conflict when trying to complete your request.\n\n resource provider generation conflict  ",
             "code": "placement.concurrent_update",
             "request_id": "req-6f0…"}]}
  • code is only present from microversion 1.23. It is placement.undefined_code when the handler supplied none (placement/util.py:30-32, placement/errors.py:42).
  • For a 406 caused by an invalid microversion, the body carries min_version and max_version.

Structured error codes (placement/errors.py:42-53)

CodeMeaningEmitted by
placement.undefined_codeerror with no specific codedefault value
placement.concurrent_updatestale provider or consumer generation, or concurrent writeinventories, allocations, traits, aggregates, reshaper
placement.inventory.inusedeletion of an inventory class that has allocationsPUT/DELETE …/inventories, reshaper
placement.duplicate_nameprovider name or uuid already takenPOST/PUT /resource_providers
placement.resource_provider.inusedeletion of a provider that has allocationsDELETE /resource_providers/{uuid}
placement.resource_provider.cannot_delete_parentdeletion of a provider that has childrensame
placement.resource_provider.not_foundunknown provider in a reshaper requestPOST /reshaper
placement.query.duplicate_keyquery parameter repeated although it must be uniqueGET /allocation_candidates, GET /resource_providers
placement.query.bad_value / placement.query.missing_valuemalformed or empty query parametersame

Catalogue by situation

400 Bad Request

Message (excerpt)SituationWhere
"Malformed JSON: …" / "JSON does not validate: …"body that is not JSON, or does not match the schema of the requested microversion: a missing field such as consumer_generation from 1.28 or consumer_type from 1.38, an invalid type, an unknown fieldplacement/util.py:69-84
"Invalid query string parameters: …"query string outside the microversion's schemaplacement/util.py:210-217
"content-type header required when content-length > 0" / "content-length header must be an integer"inconsistent headersplacement/handler.py:209-218
"Unable to create resource provider "…": parent provider UUID does not exist / cannot be same as UUID / name is required" (ObjectActionError)provider creation with an invalid parentplacement/handlers/resource_provider.py:129-133; placement/objects/resource_provider.py:563-572,690-708
"Unable to save resource provider …: re-parenting a provider is not currently allowed." / "un-parenting …" / "creating loop in the provider tree is not allowed."parent change before 1.37, or one that would create a loopplacement/objects/resource_provider.py:780-876; placement/handlers/resource_provider.py:310-313
"Invalid resource class in resources parameter" / "Invalid trait(s) in "required" parameter"GET /resource_providers or /allocation_candidates filter citing a class or trait that does not existplacement/handlers/resource_provider.py:253-261; placement/handlers/allocation_candidate.py:286-294
"Bad inventory …" / "Unable to create inventory …: Invalid inventory … The reserved value is greater than or equal to total."invalid inventory values, or reserved ≥ total (before 1.26) or reserved > total (from 1.26)placement/handlers/inventory.py:80-94,152-176,208-213
"Unknown resource class in inventory …"PUT …/inventories with a class that does not existplacement/handlers/inventory.py:347-352
"No inventory record with resource class …"PUT …/inventories/{rc} on a class absent from the inventoryplacement/handlers/inventory.py:451-456
"Allocation for resource provider '…' that does not exist."PUT/POST /allocations to an unknown provider. This is 400, not 404placement/handlers/allocation.py:329-352
"Unable to allocate inventory for consumer …: …" (NotFound)unknown resource class in an allocationplacement/handlers/allocation.py:479-483,586-588
"Malformed consumer_uuid"malformed consumer UUID in the URLplacement/handlers/allocation.py:395-398
"The "group_policy" parameter is required when specifying more than one "resources{N}" parameter."several granular groups without group_policyplacement/handlers/allocation_candidate.py:274-281
messages from placement/lib.py (orphan group, empty suffix, invalid same_subtree, trait both forbidden AND required…)inconsistent granular request syntaxplacement/lib.py:153-232,420-455
"Cannot delete standard trait / resource class …"; "Cannot update standard resource class …"change to an item that comes from os-traits or os-resource-classesplacement/handlers/trait.py:139-140; placement/handlers/resource_class.py:101-104,193-196
"The trait is invalid. A valid trait must be no longer than 255 characters, start with the prefix "CUSTOM_" …"PUT /traits/{name} with a non-custom nameplacement/handlers/trait.py:72-79
"No such trait CUSTOM_X, …"PUT /resource_providers/{uuid}/traits with a trait that does not existplacement/handlers/trait.py:237-242
"Resource provider … in inventories not found" (placement.resource_provider.not_found)reshaper citing an unknown providerplacement/handlers/reshaper.py:64-72
"malformed reshaper data"reshaper with an unknown class or consumerplacement/handlers/reshaper.py:133-136

401, 403, 404, 405, 406, 415

StatusSituationWhere
401missing or invalid token (keystonemiddleware); or a context without X_USER_IDplacement/auth.py:75-90,93-116
403 "Policy does not allow placement:… to be performed."insufficient role. Everything requires admin or service, except GET /usages (project reader) and POST /reshaper (service only). With oslo.policy ≥ 6.0.0, a token of the wrong scope is always refused, as enforce_scope can no longer be turned off (see change history, change 6)placement/handler.py:226-229; placement/policies/*.py
404resource not found: provider, class, trait, inventory of a class, or consumer with no allocation for DELETE; or existing route but microversion too low (for example GET /traits at 1.5)handlers; placement/microversion.py:130-170
405method not declared on the path (with the Allow header); DELETE …/inventories before 1.5placement/handler.py:149-174; placement/handlers/inventory.py:378
406Accept other than JSON; requested microversion outside 1.0–1.39placement/util.py (check_accept); microversion-parse
415Content-Type other than application/json on a writeplacement/util.py (require_content)

409 Conflict

Message (excerpt)CodeSituationWhere
"resource provider generation conflict" / "Resource provider's generation already changed. Please update the generation and try again."concurrent_updatethe client sends a resource_provider_generation different from the current one: inventories, traits, aggregates (≥ 1.19), reshaperplacement/handlers/inventory.py:333-336,434-437; placement/handlers/trait.py:229-233; placement/handlers/aggregate.py:118-125; placement/handlers/reshaper.py:75-83
"Update conflict: … Another thread concurrently updated the resource provider data."concurrent_updatethe generation changed between read and write, server side (UPDATE … WHERE generation = n modified no row)placement/objects/resource_provider.py:669-688
"consumer generation conflict - expected X but got Y" / "expected null but got …"concurrent_updateallocations from 1.28: stale consumer generation, or non-null generation for a consumer that does not exist yet. No server-side retryplacement/handlers/util.py:139-163
"Inventory and/or allocations changed while attempting to allocate"concurrent_updateprovider generation conflict during an allocation, after allocation_conflict_retry_count retries (10). Log: WARNING Exceeded retry limit of 10 on allocations writeplacement/handlers/allocation.py:487-491,595-599; placement/objects/allocation.py:592-596
"Unable to allocate inventory: Unable to create allocation for 'VCPU' on resource provider '…'. The requested amount would exceed the capacity."(none)not enough capacity. Log: WARNING Over capacity for VCPU on resource provider … Needed: …, Used: …, Capacity: …placement/handlers/allocation.py:484-486,592-594; placement/objects/allocation.py:272-291
"… The requested amount would violate inventory constraints."(none)amount outside min_unit, max_unit or step_sizeplacement/objects/allocation.py:229-251
"Inventory for '…' on resource provider '…' invalid."(none)allocation on a provider that has no inventory of that classplacement/objects/allocation.py:198-227
"update conflict: Inventory for '…' on resource provider '…' in use."inventory.inusePUT …/inventories that omits an allocated class, or DELETE …/inventoriesplacement/handlers/inventory.py:364-367,401-404
same**concurrent_update** (inconsistent)DELETE …/inventories/{rc} on an allocated classplacement/handlers/inventory.py:240-245
"Update conflict: …" (duplicate)concurrent_updatePOST …/inventories of a class that is already presentplacement/handlers/inventory.py:203-207
"Race condition detected when setting inventory. …"(none)inventory deleted concurrently during a PUT …/inventoriesplacement/handlers/inventory.py:353-358
"Conflicting resource provider name/uuid: … already exists."duplicate_namecreation or renaming of a provider into a duplicateplacement/handlers/resource_provider.py:104-128,305-309
"Unable to delete resource provider …: Resource provider has allocations."resource_provider.inusedeletion of an allocated providerplacement/handlers/resource_provider.py:164-168
"Unable to delete parent resource provider …: It has child resource providers."resource_provider.cannot_delete_parentdeletion of a parent providerplacement/handlers/resource_provider.py:172-176
"Conflicting resource class already exists"; "Max retries of DB transaction exceeded attempting to perform …"(none)duplicate custom class; ID allocation retries exhaustedplacement/handlers/resource_class.py:70-80,189-192
"Cannot delete resource class …. Class is in use in inventory."(none)deletion of a class in useplacement/handlers/resource_class.py:105-107
"The trait … is in use by a resource provider."(none)deletion of an attached traitplacement/handlers/trait.py:141-142
"Update conflict" (duplicate aggregate)(none)concurrent aggregate creation beyond 10 retriesplacement/handlers/aggregate.py:76-78

500 Internal Server Error

SituationWhere
any unexpected exception: unreachable database (DBConnectionError after [placement_database]/max_retries = 10 attempts spaced by retry_interval = 10 s), bug, or KeyError("… already in usage_map, bad query")placement/fault_wrap.py; placement/conf/database.py:87-94; placement/objects/allocation.py:193-195

Errors outside requests

Placement has no asynchronous processing, so no deferred error. The only errors outside an HTTP request happen:

  • at startup: unreachable database or schema behind. sync_on_startup is False by default, so placement-manage db sync must be run (placement/deploy.py:122-130). A failure while syncing the standard traits or classes prevents the application from loading [inferred];
  • in the CLI: placement-manage db online_data_migrations returns 1 or 2 when batches fail (placement/cmd/manage.py:70-131); placement-status upgrade check prints warnings (placement/cmd/status.py:38-109).

Key log messages

LevelMessageSituationWhere
WARNINGResource provider %(uuid)s is now over-capacity for %(resource)sinventory reduced below current usageplacement/objects/resource_provider.py:628-641
WARNINGOver capacity for %(rc)s on resource provider %(rp)s. Needed: …, Used: …, Capacity: …allocation refused for lack of capacityplacement/objects/allocation.py:285-291
WARNINGOver capacity … but allocation of … reduces existing overage from … to …allocation accepted on a provider already over capacityplacement/objects/allocation.py:278-284
WARNINGAllocation for … violates min_unit, max_unit, or step_size. …unit constraintsplacement/objects/allocation.py:236-246
WARNINGExceeded retry limit of %d on allocations writeheavy contention on one providerplacement/objects/allocation.py:594-595
DEBUGRetrying allocations write on resource provider generation conflictinternal allocation retryplacement/objects/allocation.py:566-567
WARNINGGot an exception when deleting auto-created consumer with UUID …cleanup after a failed allocationplacement/handlers/allocation.py:386-388
WARNINGExceeded retry limit on ID generation while …custom class creation under contentionplacement/objects/resource_class.py:137
ERROR (exception)Placement API unexpected error: …any 500placement/fault_wrap.py

Source: reverse-spec-placement/02-errors_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.