{"record":{"id":"356f17b876084038","repo":"bettercap/bettercap","slug":"expression-s-doesn-t-parse","errorCode":null,"errorMessage":"expression '%s' doesn't parse","messagePattern":"expression '(.+?)' doesn't parse","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/utils/view_selector.go","lineNumber":85,"sourceCode":"\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t} else {\n\t\ts.Expression = nil\n\t}\n\ts.filterPrev = s.Filter\n\treturn\n}\n\nfunc (s *ViewSelector) parseSorting() (err error) {\n\texpr := \"\"\n\tif err, expr = s.owner.StringParam(s.sortName); err != nil {\n\t\treturn\n\t}\n\n\ttokens := s.sortParse.FindAllStringSubmatch(expr, -1)\n\tif tokens == nil {\n\t\treturn fmt.Errorf(\"expression '%s' doesn't parse\", expr)\n\t}\n\n\ts.SortField = tokens[0][1]\n\ts.Sort = tokens[0][2]\n\ts.SortSymbol = tui.Blue(\"▾\")\n\tif s.Sort == \"asc\" {\n\t\ts.SortSymbol = tui.Blue(\"▴\")\n\t}\n\n\treturn\n}\n\nfunc (s *ViewSelector) Update() (err error) {\n\tif err = s.parseFilter(); err != nil {\n\t\treturn\n\t} else if err = s.parseSorting(); err != nil {\n\t\treturn\n\t} else if err, s.Limit = s.owner.IntParam(s.limitName); err != nil {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/bettercap/bettercap/blob/8eca2820f3c41d2004434ed5a291d87462caeeb7/modules/utils/view_selector.go#L67-L103","documentation":"ViewSelector.parseSorting reads the module's sort parameter (e.g. `sort.field asc`) and tokenizes it with a regex. If the whole expression matches no token, the selector cannot determine a sort field/direction and returns this error. It guards every view that supports sortable output.","triggerScenarios":"Setting a module's `sort` parameter (via ViewSelectorFor/Update) to a string that does not match the `<field> <asc|desc>` pattern, or to an empty/unsettable value that yields no regex matches.","commonSituations":"Typing `sort.field=asc` (with '='), omitting the direction, misspelling `asc`/`desc`, or a parameter template that expands to an empty string.","solutions":["Set the sort parameter to `<field> <asc>` or `<field> <desc>` with a single space.","Check the module's documentation for the exact accepted field name for that view.","Reset the parameter to its documented default."],"exampleFix":"// before\nset wifi.recon.sort = stations\n// after\nset wifi.recon.sort = \"stations asc\"","handlingStrategy":"validation","validationCode":"const sortExpr = params['sort'] ?? ''\nif (sortExpr !== '' && !/^[a-zA-Z0-9_.-]+\\s+(asc|desc)$/.test(sortExpr.trim())) {\n  throw new Error(`sort must look like '<field> asc|desc', got: '${sortExpr}'`)\n}","typeGuard":"function isValidSortExpr(s) { return /^[a-zA-Z0-9_.-]+\\s+(asc|desc)$/.test(s.trim()) }","tryCatchPattern":"try {\n  selector.Update()\n} catch (e) {\n  if (String(e).includes(\"doesn't parse\")) {\n    console.error('Bad sort expression; expected \"<field> asc|desc\"')\n  } else { throw e }\n}","preventionTips":["Always include an explicit asc/desc direction separated by a single space","Don't use '=' or ':' separators in the sort parameter","Consult the module docs for the valid field names of that view"],"tags":["bettercap","view-selector","sorting","parameter-validation"],"backgroundTag":"invalid-sort-expression","analyzedSha":"8eca2820f3c41d2004434ed5a291d87462caeeb7","analyzedAt":"2026-09-02T12:49:00.712Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}