{"record":{"id":"e8d22cb9a87719fc","repo":"AlexxIT/go2rtc","slug":"expr-result-is-empty","errorCode":null,"errorMessage":"expr: result is empty","messagePattern":"expr: result is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/expr/expr.go","lineNumber":23,"sourceCode":"\n\t\"github.com/AlexxIT/go2rtc/internal/app\"\n\t\"github.com/AlexxIT/go2rtc/internal/streams\"\n\t\"github.com/AlexxIT/go2rtc/pkg/expr\"\n)\n\nfunc Init() {\n\tlog := app.GetLogger(\"expr\")\n\n\tstreams.RedirectFunc(\"expr\", func(url string) (string, error) {\n\t\tv, err := expr.Eval(url[5:], nil)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\n\t\tlog.Debug().Msgf(\"[expr] url=%s\", url)\n\n\t\tif url = v.(string); url == \"\" {\n\t\t\treturn \"\", errors.New(\"expr: result is empty\")\n\t\t}\n\n\t\treturn url, nil\n\t})\n\tstreams.MarkInsecure(\"expr\")\n}\n","sourceCodeStart":5,"sourceCodeEnd":30,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/internal/expr/expr.go#L5-L30","documentation":"The expr stream source evaluates a user expression to produce a stream URL. After evaluation, if the expression result is an empty string, there is no URL to open, so the library returns this error rather than attempting to open an empty URL.","triggerScenarios":"A stream source like expr:... whose expression evaluates to \"\" — e.g. a lookup/template that returns nothing, a condition that matches no branch, or an empty environment/config value the expression reads.","commonSituations":"Dynamic URL scripts returning empty when a camera is offline or credentials are missing; regex/template producing no match; expr function referencing an unset variable.","solutions":["Ensure the expression always returns a non-empty URL string (add a default branch)","Log/debug the expression inputs; check the debug line '[expr] url=' to see what was produced","Fix whatever data the expression depends on (env var, config value, API response)","Wrap the expression so it returns a fallback URL instead of empty"],"exampleFix":"// before\nstreams:\n  cam: expr:'getURL()'\n// after\nstreams:\n  cam: expr:'u := getURL(); if u == \"\" { u = \"rtsp://fallback/stream\" }; u'","handlingStrategy":"validation","validationCode":"u := evalExpr(expr)\nif u == \"\" { return errors.New(\"expression returned empty url\") }","typeGuard":"func nonEmpty(s any) bool { v, ok := s.(string); return ok && v != \"\" }","tryCatchPattern":"url, err := tryOpen(src); if err != nil && err.Error() == \"expr: result is empty\" { url = fallbackURL }","preventionTips":["Give every expr a default/fallback return value","Watch the '[expr] url=' debug log line when debugging dynamic sources","Validate inputs the expression depends on (env, config, upstream API)"],"tags":["expr","empty-result","dynamic-url","go2rtc"],"backgroundTag":"empty-required-field","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}