{"record":{"id":"41306af10889aa0c","repo":"AlexxIT/go2rtc","slug":"api-streamnotfound-41306a","errorCode":null,"errorMessage":"api.StreamNotFound","messagePattern":"api\\.StreamNotFound","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/homekit/api.go","lineNumber":154,"sourceCode":"\n\treturn sources, nil\n}\n\nfunc apiPair(id, url string) error {\n\tconn, err := hap.Pair(url)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tstreams.New(id, conn.URL())\n\n\treturn app.PatchConfig([]string{\"streams\", id}, conn.URL())\n}\n\nfunc apiUnpair(id string) error {\n\tstream := streams.Get(id)\n\tif stream == nil {\n\t\treturn errors.New(api.StreamNotFound)\n\t}\n\n\trawURL := findHomeKitURL(stream.Sources())\n\tif rawURL == \"\" {\n\t\treturn errors.New(\"not homekit source\")\n\t}\n\n\tif err := hap.Unpair(rawURL); err != nil {\n\t\treturn err\n\t}\n\n\tstreams.Delete(id)\n\n\treturn app.PatchConfig([]string{\"streams\", id}, nil)\n}\n\nfunc findHomeKitURLs() map[string]*url.URL {\n\turls := map[string]*url.URL{}","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/internal/homekit/api.go#L136-L172","documentation":"apiUnpair removes a HomeKit pairing bound to a go2rtc stream. It first fetches the stream by id via streams.Get; if no stream with that id exists it returns the shared api.StreamNotFound sentinel error, because there is nothing to unpair.","triggerScenarios":"DELETE/POST to the HomeKit unpair API with an id that doesn't match any configured stream; stream deleted before unpair; id case/typo mismatch.","commonSituations":"Stale HomeKit accessory cache referencing deleted streams; renaming a stream then unpairing by the old name; automation calling unpair twice (second call hits it).","solutions":["Check the stream id via GET /api/streams and unpair with an existing id","Restore the stream in the config if it was removed unintentionally","Treat StreamNotFound as already-unpaired in automation and ignore it"],"exampleFix":"// before\nawait fetch('/api/homekit/unpair?id=old_cam')\n// after\nawait fetch('/api/homekit/unpair?id=cam1')  // id that exists in streams","handlingStrategy":"validation","validationCode":"const streams = await (await fetch('/api/streams')).json()\nif (!(id in streams)) return // already unpaired or wrong id\nawait fetch('/api/homekit/unpair?id=' + id)","typeGuard":null,"tryCatchPattern":"const res = await fetch('/api/homekit/unpair?id='+id); if (res.status !== 200) { /* id may not exist; treat as already unpaired */ }","preventionTips":["Validate the id against /api/streams before unpair calls","Clean up HomeKit pairings when deleting streams, not after","Make automation idempotent: ignore StreamNotFound on unpair"],"tags":["homekit","stream-not-found","api","go2rtc"],"backgroundTag":"resource-not-found","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"}