solidjs/solid · error · TypeError
Expected the observer to be an object.
Error message
Expected the observer to be an object.
What it means
Thrown by observable().subscribe() when the argument is not an object. The observable interop wraps a Solid accessor in an RxJS-style Observable, and the spec requires the observer to be either a function or an object with a next method. Solid validates this up front and throws a TypeError for null, undefined, or primitives.
Source
Thrown at packages/solid/src/reactive/observable.ts:50
next?: (v: T) => void;
error?: (v: any) => void;
complete?: (v: boolean) => void;
};
/**
* Creates a simple observable from a signal's accessor to be used with the `from` operator of observable libraries like e.g. rxjs
* ```typescript
* import { from } from "rxjs";
* const [s, set] = createSignal(0);
* const obsv$ = from(observable(s));
* obsv$.subscribe((v) => console.log(v));
* ```
* description https://docs.solidjs.com/reference/reactive-utilities/observable
*/
export function observable<T>(input: Accessor<T>): Observable<T> {
return {
subscribe(observer: ObservableObserver<T>) {
if (!(observer instanceof Object) || observer == null) {
throw new TypeError("Expected the observer to be an object.");
}
const handler =
typeof observer === "function" ? observer : observer.next && observer.next.bind(observer);
if (!handler) {
return { unsubscribe() {} };
}
const dispose = createRoot(disposer => {
createEffect(() => {
const v = input();
untrack(() => handler(v));
});
return disposer;
});
View on GitHub (pinned to f47845f9cc)
Solutions
- Pass either a plain function or an object with a next method: subscribe({ next: v => ... })
- Default the observer: subscribe(observer || { next: () => {} })
- If interoperating with RxJS, pipe the Solid observable into RxJS's from() rather than hand-writing observers
Example fix
// before
const obs = observable(signal);
obs.subscribe(maybeObserver); // maybeObserver is undefined
// after
const obs = observable(signal);
const sub = obs.subscribe(
maybeObserver ?? { next: (v) => console.log(v) }
);
sub.unsubscribe(); Defensive patterns
Strategy: type-guard
Validate before calling
function isObserver(v: unknown): v is ((v: T) => void) | { next: (v: T) => void } {
return typeof v === 'function' || (!!v && typeof (v as any).next === 'function');
}
if (!isObserver(observer)) throw new Error('observer must be function or { next }');
observable(accessor).subscribe(observer as any); Type guard
const isObserver = (v: unknown): v is { next: (v: unknown) => void } | ((v: unknown) => void) =>
typeof v === 'function' ||
(v instanceof Object && typeof (v as { next?: unknown }).next === 'function'); Try / catch
try { obs.subscribe(observer); } catch (e) { if (e instanceof TypeError && /observer to be an object/.test(e.message)) fixObserverShape(); else throw e; } Prevention
- Always construct observers as a function or { next } object literal at the call site
- Default optional observers: observer ?? (() => {})
- Type the observer parameter in your own wrappers so TS rejects primitives
When it happens
Trigger: Calling observable(accessor).subscribe(null), subscribe(42), subscribe('x'), or an object without a next method combined with a non-function value; also de-serializing or cloning an observer so it arrives as a primitive.
Common situations: Passing an observer variable that is conditionally undefined; mixing up RxJS subscriber APIs (passing a config object instead of observer); migrating code where a function observer was refactored into an optional object.
Related errors
- Expected the observer to be an object.
- Unexpected type ${typeof unwrappedStore} received when initi
- Unexpected type ${typeof unwrappedStore} received when initi
- Dispose method must be an explicit argument to createRoot fu
- Potential Infinite Loop Detected.
AI-assisted analysis of solidjs/solid@f47845f9cc (2026-08-27).
Data as JSON: /api/errors/0f2ca31f48077946.
Report an issue: GitHub.