The observed behaviour will appear in any expression whose symbolic head has the attribute `Flat`. Under normal circumstances, with no attributes in play, we see the usual expected behaviour: MatchQ[f[1], f[1]] (* True *) MatchQ[f[1], f[a_]] (* True *) MatchQ[f[1], f[f[1]]] (* False *) MatchQ[f[1], f[f[a_]]] (* False *) MatchQ[f[1, 2, 3], f[a_]] (* False *) But when we introduce the `Flat` attribute, our normal intuition no longer holds: SetAttributes[g, Flat] MatchQ[g[1], g[1]] (* True*) MatchQ[g[1], g[a_]] (* True*) MatchQ[g[1], g[g[1]]] (* True*) MatchQ[g[1], g[g[a_]]] (* True *) MatchQ[g[1, 2, 3], g[a_]] (* True *) **What is happening?** The purpose of `Flat` is to flatten out any nested expressions. That is, `g[g[1, 2, 3]]` is to be treated as equivalent to `g[1, 2, 3]`. The key point is that this equivalence works both ways. So when we ask whether `g[1, 2, 3]` matches the pattern `g[a_]`, then this is equivalent to asking whether `g[g[1, 2, 3]]` matches `g[a_]`. Which of course it does. That is why the `MatchQ` expression in the question returns `True`. As does `MatchQ[g[g[g[g[g[1, 2, 3]]]]], g[a_]]` **Can we turn it off?** A simple way to perform the exact match requested by the question is to temporarily remove the `Flat` attribute from `Times`. `Block` will strip `Times` of all of its attributes: Block[{Times} , MatchQ[ HoldComplete[Times[3, 2, 2]] , HoldComplete[Times[a_]] ] ] (* False *) If, for some reason, the application is such that we wish to retain the other attributes of `Times`, we can use ``Internal`InheritedBlock``: Attributes[Times] (* {Flat, Listable, NumericFunction, OneIdentity, Orderless, Protected} *) Internal`InheritedBlock[{Times} , Unprotect[Times] ; ClearAttributes[Times, Flat] ; Protect[Times] ; { MatchQ[ HoldComplete[Times[3, 2, 2]] , HoldComplete[Times[a_]] ] , Attributes[Times] } ] (* {False, {Listable, NumericFunction, OneIdentity, Orderless, Protected}} *)