* server: guard plugin-repl against stale nativeId
The REPL handler destructured nativeIds.get(filter) directly, which
threw an unhandledRejection TypeError when filter was a nativeId for a
device that had been removed since the UI rendered the REPL link.
Break out of the chain walk when the lookup misses instead.
Assisted-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Sergey Vilgelm <sergey@vilgelm.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Signed-off-by: Sergey Vilgelm <sergey@vilgelm.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* docs: clarify avahi config for host vs bridge networking
The HomeKit plugin's MDNSServer binds UDP port 5353 directly on every
network interface. With network_mode: host (the default), this conflicts
with any system avahi-daemon running on the host, causing EADDRINUSE on
all interfaces and silently breaking HomeKit mDNS discovery.
The previous comments implied the host socket mount and
SCRYPTED_DOCKER_AVAHI=true were equivalent alternatives ("choose one or
the other"), which is misleading. Clarify the two distinct use cases:
- Option A (host networking): SCRYPTED_DOCKER_AVAHI=true is required.
The host avahi-daemon must be stopped. The /var/run socket mounts are
incompatible with this mode. Add a note about mounting
/etc/avahi/services to preserve host service advertisements.
- Option B (bridge networking only): host socket mount works because
Scrypted registers via D-Bus without binding 5353. Does not work with
host networking.
Fixes#2013
* fix: use SCRYPTED_DOCKER_AVAHI=true for avahi setup with host networking
The install script was configuring the host avahi socket mount (Option B)
while the template uses network_mode: host. This is a broken combination:
the HomeKit plugin's MDNSServer binds UDP 5353 directly on every interface,
conflicting with the system avahi-daemon, causing EADDRINUSE on all
interfaces and silently breaking HomeKit mDNS discovery.
Fix: when the user opts in to avahi, use SCRYPTED_DOCKER_AVAHI=true
(Option A) instead. This makes Scrypted run its own internal avahi.
Also stop/disable the host avahi-daemon so it doesn't conflict, and
mount /etc/avahi/services:ro so Scrypted's avahi picks up existing host
service definitions (e.g. Time Machine, Samba).
Fixes#2013
* fix: show stream selection options when synthetic streams are configured
* fix: show stream selection options and enforce FFmpeg parser for synthetic streams
Fix strictNullChecks:
- device.ts: add assertions for storage and nativeIds access
- endpoint.ts: add assertions for device and handler access
- plugin-api.ts: add definite assignment for callback properties
- plugin-host-api.ts: add assertions for findPluginDevice results,
consolidate plugin assertions at declarations
- plugin-lazy-remote.ts: add assertion for getFile result
- system.ts: add definite assignment for manager properties,
add assertions for state access
Fix strictNullChecks:
- plugin-device.ts: consolidate entry/host assertions at declarations,
use undefined! for proxy values, add definite assignment for mixinTable
- plugin-remote.ts: add assertions for callbacks and nativeIds access
- plugin-remote-worker.ts: fix clusterWorkerId as Promise<string | undefined>,
add assertions for worker and options properties
Fix strictNullChecks in runtime.ts and scrypted-server-main.ts:
- Change findPluginDevice return type to PluginDevice | undefined
- Add type assertions at call sites that expect valid results
- Consolidate assertions at variable declarations
- Use undefined! instead of undefined as any
- Use throw e instead of throw new Error(e as string)
- Add catch block type annotations (e: any)
- Fix socket property and plugin device lookups with assertions
Fix strictNullChecks in services:
- plugin.ts: assert findPluginDeviceById results at assignment point,
clean up scattered assertions throughout methods
- users.ts: make aclId parameter optional in addUserToDatabase/addUserInternal
- Make PluginRemote.loadZip options parameter optional to match implementations
- Add undefined to _protocols type in WebSocket class
- Add non-null assertions for device lookup in REPL server
- Add non-null assertion for eventInterface in acl.ts
- Add non-null assertion for SCRYPTED_CLUSTER_ADDRESS env var
- Use .flat() instead of [].concat() for type safety
- Add non-null assertion for ScryptedDevice descriptor access
- Use options! and null! assertions for mediaObject properties
- Initialize foundAny variable before use
- Add fallback for undefined env var in parseFloat
- Add non-null assertions for Map lookups and array indices
- Fix ClusterObject type annotation for undefined case
- Add non-null assertions for env vars and socket properties
- Add type assertions for event callbacks and timestamps
- Use non-null assertions for guaranteed object references
- Update notify signature to accept number | undefined for eventTime
- Preserve crash behavior for logger and refresh throttle access
- setStorage interface uses ScryptedNativeId to match implementation
- getDeviceById returns Promise<ScryptedDevice | undefined>
- Add non-null assertions where objects are guaranteed to exist
- Add explicit error throws for null checks with descriptive messages
- Add parseInt with empty string fallback for undefined env vars
- getIpAddress returns string | undefined when no addresses available
- Add type guard filters for network interface arrays
Previously, if this.serialize() threw an exception, result would be undefined
when passed to createErrorResult. This fix brings TypeScript in sync with the
Python rpc.py implementation which already initializes result before the try block.
Check serviceKey directly after parsing instead of checking existing?.serviceKey.
This fixes a bug where key parsing failures would be silently ignored.