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

Reverse-spec · Clients

python-neutronclient — Errors

Errors — python-neutronclient — branch stable/2026.2

Branch stable/2026.2 @ 596a9d99b188 (14.0.0 + 2 maintenance commits) — repository https://opendev.org/openstack/python-neutronclient — analysed on 2026-11-01

Every [observed] run is in [_rewrite/defect-repros_stable-2026.2.json](_rewrite/defect-repros_stable-2026.2.json), under the ID given in parentheses. The stub is not Neutron: these runs show how the client reacts to a given response, not that a real service sends it.

1. Exit codes

ExitSituationSource
0the command returned nothing, or the columns and data of a ShowOne or Listercliff:cliff/command.py:196
1any exception in take_action: cliff logs str(exception) to stderr. There is no traceback without --debugcliff:cliff/app.py:462, cliff:cliff/app.py:467
2argparse rejected the arguments (log-create-bad-event, fc-create-bad-ethertype, pp-create-bad-key), or the command does not exist (load-api-version-3)cliff:cliff/app.py:428

Some validation runs after parsing, and so exits 1, not 2: --source-port :5 (fc-create-port-empty), --branching-point a (graph-no-colon).

2. Exceptions of the Python library

All are in neutronclient/common/exceptions.py. The library has three groups, as the module docstring says (neutronclient/common/exceptions.py:20-31).

HTTP status → exception

exception_handler_v20 chooses the class in this order (neutronclient/v2_0/client.py:46-92):

  1. if the body has NeutronError with type, message and detail: the class <type>Client in the exceptions module, if it exists;
  2. otherwise the class for the status;
  3. otherwise NeutronClientException.
StatusClassDefault messageDefined at
400BadRequestserver textneutronclient/common/exceptions.py:92
401UnauthorizedUnauthorized: bad credentials.neutronclient/common/exceptions.py:96
403ForbiddenForbidden: your credentials don't give you access to this resource.neutronclient/common/exceptions.py:101
404NotFoundserver textneutronclient/common/exceptions.py:107
409Conflictserver textneutronclient/common/exceptions.py:111
500InternalServerErrorserver textneutronclient/common/exceptions.py:115
503ServiceUnavailableserver textneutronclient/common/exceptions.py:119
other non-2xx, and 2xx other than 200, 201, 202, 204NeutronClientExceptionserver textneutronclient/common/exceptions.py:64, neutronclient/v2_0/client.py:291

status_code and request_ids are set on the instance, and the message ends with Neutron server returns request_ids: […] when the response has that header (neutronclient/common/exceptions.py:76-87).

NeutronError.type → exception

A compatible service must keep these type names, since the projects below catch these classes.

type in the bodyClassBaseDefined at
NetworkNotFoundNetworkNotFoundClientNotFoundneutronclient/common/exceptions.py:139
PortNotFoundPortNotFoundClientNotFoundneutronclient/common/exceptions.py:143
StateInvalidStateInvalidClientBadRequestneutronclient/common/exceptions.py:147
NetworkInUseNetworkInUseClientConflictneutronclient/common/exceptions.py:151
PortInUsePortInUseClientConflictneutronclient/common/exceptions.py:155
IpAddressInUseIpAddressInUseClientConflictneutronclient/common/exceptions.py:159
IpAddressAlreadyAllocatedIpAddressAlreadyAllocatedClientConflictneutronclient/common/exceptions.py:163
InvalidIpForNetworkInvalidIpForNetworkClientBadRequestneutronclient/common/exceptions.py:167
InvalidIpForSubnetInvalidIpForSubnetClientBadRequestneutronclient/common/exceptions.py:171
OverQuotaOverQuotaClientConflictneutronclient/common/exceptions.py:175
IpAddressGenerationFailureIpAddressGenerationFailureClientConflictneutronclient/common/exceptions.py:179
MacAddressInUseMacAddressInUseClientConflictneutronclient/common/exceptions.py:183
HostNotCompatibleWithFixedIpsHostNotCompatibleWithFixedIpsClientConflictneutronclient/common/exceptions.py:187
ExternalIpAddressExhaustedExternalIpAddressExhaustedClientBadRequestneutronclient/common/exceptions.py:191

Projects can add to this list by monkey-patching the module: Manila adds PortBindingAlreadyExistsClient (manila:manila/network/neutron/api.py:80).

Exceptions raised by the library itself

ClassMessageSituationRaised at
ConnectionFailedConnection to neutron failed: %(reason)sany exception in the HTTPClient path; and after the retries, with Failed to connect Neutron serverneutronclient/client.py:114, neutronclient/v2_0/client.py:352
SslCertificateValidationErrorSSL certificate validation has failed: %(reason)sTLS failure in the HTTPClient pathneutronclient/client.py:108
Unauthorizedbody text401 in the HTTPClient path; a non-200 from POST /tokens; noauth without an endpoint; unknown strategyneutronclient/client.py:128, neutronclient/client.py:245, neutronclient/client.py:260, neutronclient/client.py:269
NoAuthURLProvidedauth_url was not provided to the Neutron clientkeystone strategy without auth_urlneutronclient/client.py:237, neutronclient/client.py:273
EndpointTypeNotFoundCould not find endpoint type %(type_)s in Service Catalog.legacy endpoint lookupneutronclient/client.py:289
EndpointNotFoundCould not find Service or Region in Service Catalog.legacy endpoint lookupneutronclient/client.py:293
RequestURITooLongsee § 4endpoint + action longer than 8,192 characters, checked before sendingneutronclient/client.py:180, neutronclient/client.py:336
MalformedResponseBodyMalformed response body: Cannot understand JSONsuccess body that is not JSON (log-list-not-json)neutronclient/common/serializer.py:71
InvalidContentTypeInvalid content type %(content_type)s.unreachable: the type is always JSONneutronclient/common/serializer.py:98, neutronclient/common/serializer.py:120
NotFoundUnable to find %(resource)s with name or id '%(name_or_id)s'find_resource without a match (log-show-missing)neutronclient/v2_0/client.py:491
NeutronClientNoUniqueMatchMultiple %(resource)s matches found for name '%(name)s', use an ID to be more specific.two resources with that name (log-show-two-names)neutronclient/v2_0/client.py:464
UnsupportedVersionInvalid %(api_name)s client version …neutron.client.Client with another versionneutronclient/common/utils.py:70
CommandError (of this package)Protocol port value %s must be an integer or integer:integer.--source-port a:b (fc-create-port-text)neutronclient/osc/v2/sfc/sfc_flow_classifier.py:346

AmbiguousEndpoints (neutronclient/common/exceptions.py:209) is never raised, and its template %(matching_endpoints) lacks the conversion type.

Error body → text

Response [observed]Shown to the userRun
{"NeutronError": {"type":…, "message":"m", "detail":"d"}}m and d on two lineserror-with-detail
same, without detail{'type': 'BadRequest', 'message': 'm'}error-no-detail
{"NeutronError": "plain text"}plain texterror-plain-string
{"message": "forbidden text"}forbidden texterror-message-key
<html>down</html>, 503the HTML texterror-html
empty body, 502Bad Gateway (the HTTP reason)error-empty
{"error": {"message": "denied"}}, 401, twice401-{'error': {'message': 'denied'}}error-401-always
JSON list, 500'NoneType' object has no attribute 'request_ids'error-json-list
SDK command, 409 with detailConflictException: 409: Client Error for url: …, m; the SDK reads message only (openstacksdk:openstack/exceptions.py:197)sdk-error-with-detail

401: keystoneauth invalidates the token and retries once (keystoneauth1:keystoneauth1/session.py:1130). error-401-once exits 0 after two GET; error-401-always sends two GET and fails.

3. Messages of the commands

Generated from the code. CommandError here is osc_lib.exceptions.CommandError, unless stated otherwise.

Message (template)ExceptionRaised atCommands
%(result)s of %(total)s flow classifier(s) failed to delete.CommandErrorneutronclient/osc/v2/sfc/sfc_flow_classifier.py:175sfc flow classifier delete
%(result)s of %(total)s network log(s) failed to deleteCommandErrorneutronclient/osc/v2/logging/network_log.py:188network log delete
%(result)s of %(total)s port chain(s) failed to delete.CommandErrorneutronclient/osc/v2/sfc/sfc_port_chain.py:133sfc port chain delete
%(result)s of %(total)s port pair group(s) failed to delete.CommandErrorneutronclient/osc/v2/sfc/sfc_port_pair_group.py:137sfc port pair group delete
%(result)s of %(total)s port pair(s) failed to delete.CommandErrorneutronclient/osc/v2/sfc/sfc_port_pair.py:130sfc port pair delete
%(result)s of %(total)s service graph(s) failed to delete.CommandErrorneutronclient/osc/v2/sfc/sfc_service_graph.py:150sfc service graph delete
(built at run time)CommandError, CommandErrorneutronclient/osc/v2/sfc/sfc_flow_classifier.py:346, neutronclient/osc/v2/sfc/sfc_service_graph.py:262, neutronclient/osc/v2/sfc/sfc_service_graph.py:267sfc flow classifier create, sfc flow classifier set, sfc service graph create (+1)
At least one --port-pair-group must be specified.CommandErrorneutronclient/osc/v2/sfc/sfc_port_chain.py:230sfc port chain set
At least one port pair group must be specified.CommandErrorneutronclient/osc/v2/sfc/sfc_port_chain.py:343sfc port chain unset
Error: Service graph contains a cycleCommandErrorneutronclient/osc/v2/sfc/sfc_service_graph.py:216sfc service graph create, sfc service graph set
Error: you must specify at least one destination chain for each source chainCommandErrorneutronclient/osc/v2/sfc/sfc_service_graph.py:219sfc service graph create, sfc service graph set
Error: You must specify at least one destination chain for each source chain.CommandErrorneutronclient/osc/v2/sfc/sfc_service_graph.py:251sfc service graph create, sfc service graph set
Failed to create service graph using '%(pcs)s': %(e)sCommandErrorneutronclient/osc/v2/sfc/sfc_service_graph.py:81sfc service graph create
Failed to onboard subnets for network '%(n)s': %(e)sCommandErrorneutronclient/osc/v2/subnet_onboard/subnet_onboard.py:55network onboard subnets
Failed to set network log '%(logging)s': %(e)sCommandErrorneutronclient/osc/v2/logging/network_log.py:283network log set
Failed to unset port chain '%(pc)s': %(e)sCommandErrorneutronclient/osc/v2/sfc/sfc_port_chain.py:350sfc port chain unset
Failed to unset port pair group '%(ppg)s': %(e)sCommandErrorneutronclient/osc/v2/sfc/sfc_port_pair_group.py:288sfc port pair group unset
Failed to update flow classifier '%(fc)s': %(e)sCommandErrorneutronclient/osc/v2/sfc/sfc_flow_classifier.py:268sfc flow classifier set
Failed to update port chain '%(pc)s': %(e)sCommandErrorneutronclient/osc/v2/sfc/sfc_port_chain.py:256sfc port chain set
Failed to update port pair '%(port_pair)s': %(e)sCommandErrorneutronclient/osc/v2/sfc/sfc_port_pair.py:188sfc port pair set
Failed to update port pair group '%(ppg)s': %(e)sCommandErrorneutronclient/osc/v2/sfc/sfc_port_pair_group.py:219sfc port pair group set
Failed to update service graph '%(service_graph)s': %(e)sCommandErrorneutronclient/osc/v2/sfc/sfc_service_graph.py:116sfc service graph set
Invalid port value '%s', expected format is min-port:max-port or min-port.ArgumentTypeErrorneutronclient/osc/v2/sfc/sfc_flow_classifier.py:337sfc flow classifier create, sfc flow classifier set

The row "built at run time" covers: Protocol port value %s must be an integer or integer:integer. (neutronclient/osc/v2/sfc/sfc_flow_classifier.py:346), Error: Duplicate destination chains from source chain {} (neutronclient/osc/v2/sfc/sfc_service_graph.py:262), and Error: Source chain {} is in use already (neutronclient/osc/v2/sfc/sfc_service_graph.py:267).

Logged and not raised: Failed to delete … with name or ID '…': …, once per failed item, before the final count (neutronclient/osc/v2/logging/network_log.py:180, neutronclient/osc/v2/sfc/sfc_flow_classifier.py:169, neutronclient/osc/v2/sfc/sfc_port_chain.py:126, neutronclient/osc/v2/sfc/sfc_port_pair.py:122, neutronclient/osc/v2/sfc/sfc_port_pair_group.py:130, neutronclient/osc/v2/sfc/sfc_service_graph.py:142).

Logged on stderr by each of the 7 binding commands, at level warning, with exit 0 [observed: warning-on-python-binding]: The python binding code in neutronclient is deprecated in favor of OpenstackSDK, please use that as this will be removed in a future release. (neutronclient/v2_0/client.py:253).

4. Defects found

Only what was reproduced on the stub or read in the code. All pass the unit tests, because these mock the clients (neutronclient/tests/unit/osc/v2/fakes.py:27-30).

#DefectEffectWhereEvidence
1sfc port pair group set calls find_sfc_port_pair_group without ignore_missing=False, unlike every other SFC command. The SDK default is True (openstacksdk:openstack/network/v2/_proxy.py:9559), so a missing group gives None, then ['id'] fails'NoneType' object is not subscriptable, exit 1, instead of No SfcPortPairGroup found for missingneutronclient/osc/v2/sfc/sfc_port_pair_group.py:197[observed] ppg-set-missing; control ppg-show-missing-control, ppg-unset-missing-control
2_visit assigns the recursive result to found_cycle and tests it only on the next iteration; when the last destination holds the cycle, the loop ends and it returns False--branching-point a:b --branching-point b:c --branching-point c:a is sent to the server, exit 0. a:b b:a and a:a are refused. Whether a server refuses it was not testedneutronclient/osc/v2/sfc/sfc_service_graph.py:233-241[observed] graph-cycle-3-missed; control graph-cycle-2-detected, graph-self-loop
3event is assigned only when d['event'] is truthy, and read unconditionallyfirst row without event: cannot access local variable 'event' where it is not associated with a value, exit 1. Later row: shows the previous row's event, exit 0, which misleadsneutronclient/osc/v2/logging/network_log.py:228-243[observed] log-list-event-none-first, log-list-event-stale
4network log list reads event, target_id, resource_type and resource_id by keya missing key prints 'target_id' alone, exit 1neutronclient/osc/v2/logging/network_log.py:228-233[observed] log-list-no-target-key
5_convert_into_with_meta turns an empty JSON object into an empty tuple, and a non-empty list into None200 {}: tuple indices must be integers or slices, not str; 200 [1]: 'NoneType' object is not subscriptable; {"other": []}: 'logs'; 201 {} on create: same tuple errorneutronclient/v2_0/client.py:403-410, neutronclient/v2_0/client.py:376[observed] log-list-empty-object, log-list-json-list, log-list-no-collection, log-create-empty-object
6error_dict['detail'] raises KeyError inside a broad trya Neutron error without detail shows a Python dict, and the <type>Client class is not chosen, since the lookup comes afterneutronclient/v2_0/client.py:64-72[observed] error-no-detail
7An error body that is a non-empty JSON list becomes None, then .request_ids fails'NoneType' object has no attribute 'request_ids' hides the statusneutronclient/v2_0/client.py:56, neutronclient/v2_0/client.py:273[observed] error-json-list
8RequestURITooLong has no message, so it inherits the base text; status_code stays 0, and its docstring speaks of an HTTP 414 though it is raised before sendingAn unknown exception occurred., exit 1, no request sentneutronclient/common/exceptions.py:214-219, neutronclient/common/exceptions.py:49[observed] uri-too-long, python-api
9An unknown --resource-type with --resource goes through getattr(self, "list_%s" …)'Client' object has no attribute 'list_foos', exit 1, no request. Without --resource, the type goes to the server uncheckedneutronclient/v2_0/client.py:451, neutronclient/osc/v2/logging/network_log.py:86[observed] log-create-unknown-type
10network log set --description "" and --name "" test truthinessthe value is dropped; PUT {"log": {}}, exit 0: the description cannot be cleared. SFC commands test is not Noneneutronclient/osc/v2/logging/network_log.py:101-104[observed] log-set-clear-description
11sfc flow classifier list joins l7_parametersa response without that field gives can only join an iterable, exit 1. The field being read by key on an SDK resource yields Noneneutronclient/osc/v2/sfc/sfc_flow_classifier.py:207[observed] fc-list-no-l7
12Without a session, HTTPClient authenticates with the Keystone v2 body at {auth_url}/tokensa 404 from Keystone becomes Unauthorized carrying the body. The class docstring shows this usage (neutronclient/v2_0/client.py:234-241). On real Keystone v3 the same path is expected [inferred]neutronclient/client.py:221-245[observed] python-api: password-v3-url, password-root-url
13The release note says that all CLI code was removed; 63 files remainnone at run timereleasenotes/notes/remove-cli-code-53969e9aa927e530.yaml:10read

Not defects, but traps [observed]:

  • network log create --project p with a 403 from Keystone sends the name as project_id (log-create-project-forbidden, neutronclient/osc/utils.py:113-116). This is deliberate, says the docstring.
  • A catalog without network gives public endpoint for network service in RegionOne region not found on binding commands, and a longer SDK text on sfc commands (catalog-no-network-log, catalog-no-network-sfc). No crash.
  • --port-pair-group-parameters foo=bar passes any key to the server (ppg-create-other-key).

5. Asynchronous errors

None. The process exits with the first failure, except for the loops in the delete commands. See 05.

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