Status code · Address space

BadTooManyMatches

BadBrowse paths

BadTooManyMatches means your request matched more targets than the server will return. It comes from under-specified browse paths and broad queries: an empty target name, a path element that matches every child, or a filter with nothing to narrow it. Make the path specific, or switch to Browse with a NodeClassMask and BrowseNext.

Defined behaviour: The requested operation has too many matches to return. (our description of the condition this code reports)

What you actually see

A path translation or query fails only against the largest machines or the busiest servers, while the same request succeeds on a small test address space.

Why it happens

  • An empty or wildcard target nameA RelativePathElement with no target name matches every target reachable by the specified reference type. Against a folder with thousands of children that is a legitimate request the server cannot sensibly answer, so it refuses rather than returning an enormous result.
  • A path element with no reference type restrictionLeaving the reference type unrestricted with subtypes included pulls in components, properties, organised children and type references at once. Combined with a loose target name, the match count grows quickly.
  • Duplicate BrowseNames across namespacesTwo children can carry the same name text in different namespaces. A path element that specifies only the text can match both, which is exactly why the namespace part of a QualifiedName is not optional.
  • A broad query against a large address spaceWhere the server supports query, a filter that is not selective enough matches most of the model. The same request is harmless on a demo server and impossible on a plant server with hundreds of thousands of nodes.
  • Server-side result capsServers bound the number of results a single operation may return in order to protect themselves. Hitting the cap is a signal to restructure the traversal rather than to raise the limit.

How to fix it

In diagnostic order: work down, do not skip ahead.

  1. Make every path element fully qualifiedGive each RelativePathElement an explicit target QualifiedName with its namespace index, an explicit ReferenceTypeId, and an explicit direction. A fully specified path matches one target or none, never thousands.
  2. Split the traversal into stepsResolve the path one or two elements at a time, checking the result of each step. It costs an extra round trip and it turns an unanswerable request into a sequence of trivially answerable ones.
  3. Use Browse rather than a path when you want a listIf you actually want all children, that is a Browse, not a browse-path translation. Set MaxReferencesPerNode, filter with ReferenceTypeId, IncludeSubtypes, NodeClassMask and ResultMask, and page with BrowseNext continuation points.
  4. Filter on NodeClass and reference type at the serverAsk for Variables only, or components only, rather than everything followed by client-side filtering. Filtering at the server reduces both the match count and the message size.
  5. Drive the traversal from the typeBrowse the ObjectType to learn the structure, then locate instances of that type, which is exactly how the umati dashboard client walks its machines. Type-driven traversal keeps the match count bounded by the model rather than by the plant.

Where it shows up, by tool and stack

Tool / stackWhat to do there
UaExpertBrowsing a folder with a very large number of children is visibly slow and is exactly the situation where a path translation will refuse. Treat a slow browse tree as a warning that your traversal needs narrowing.
node-opcuaBrowse descriptions accept nodeClassMask and resultMask explicitly. Setting them is the difference between a manageable result and one the server declines to produce.
asyncua (Python)Prefer node.get_child with fully prefixed names over broad path constructs, and use browse with a nodeclassmask when you genuinely want a list of children.
OPC PublisherStreaming browse and partial nodeset export exist specifically for large address spaces. Use them rather than trying to resolve broad paths against a plant-scale server.
Siemens S7-1500A controller address space can be large and the server shares CPU with the control task. Narrow every traversal and browse once at commissioning rather than repeatedly at runtime.

What it looks like in the log

TranslateBrowsePathsToNodeIds returned BadTooManyMatches for path element with empty target name
Query matched 41208 nodes; server limit exceeded
Browse of ns=4;s=Plant returned 65000 references; consider MaxReferencesPerNode

Confirm the fix

Re-issue the narrowed request and confirm it returns a bounded, expected number of targets, then confirm a full traversal of the area completes with BrowseNext rather than by widening the path.

Stop it happening again

Never leave a target name or reference type unspecified in production code, prefer Browse with filters and continuation points for lists, and use type-driven traversal so the cost of a walk depends on the model rather than on plant size.

Stuck on more than one of these? The troubleshooting clinic works through broken configurations end to end, on camera.

Troubleshooting clinic →

Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.

Free download
OPC UA Status Code Diagnostic Tree
A 15-page diagnostic reference grouping every normative status code by what actually went wrong: with the first action for each, and the four questions that resolve most faults before you read a single code.
Get the free diagnostic tree →
Free, no course, no login