Skip to content
View in the app

A better way to browse. Learn more.

ernestdefoe.online

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
ernestdefoe.online

Extensions, themes & support for Flarum and Invision Community

Vibe coding for the community web. Report a bug, request a feature, or dig into the source — this is where the tools you use get built, in the open.

We do custom Bespoke Invision Community apps. If you have an idea for something you want then use the contact form to get in touch with us.
Knowledge base

Things that cost me a day, so they cost you none

Working notes from building Invision Community and Flarum applications. Mostly the failures that give no error at all — the ones where everything installs cleanly and quietly does the wrong thing.

92 articles

Invision Community 5

86 articles

Extensions and contracts

39

What each extension point is for, what it must declare, and what happens when it is wrong — which is usually nothing visible.

Languages and text

5

The string table, translation, and the places where text does not appear where you expected it to.

Theming, templates and forms

9

Theme hooks, CSS that survives both colour schemes, and building forms that do not throw on render.

Background work and scheduled tasks

5

The queue system, work that has to happen after the response, and jobs that finish without doing anything.

Data, settings and storage

11

The database layer, settings, tags, file storage, and backing up a live site.

AI features and expectations

5

What these features do, what they cost, and what buyers reasonably but wrongly assume they do.

Application structure and releases

11

The JSON files an application is made of, versioning and upgrade steps, and testing from the command line.

Realtime, chat and calls

1

WebSocket gateways, relays and the server-side pieces live features depend on — where "it works when I test it" and "it works for your members" are different claims.

Nothing matches that.

A chat model in an embeddings field fails silently, and looks like a broken app

An OpenAI API key works with both endpoints. The model names do not. Put gpt-5.4-nano, gpt-4o-mini or any other chat model into a field that expects an embeddings model, and the request is rejected — but if the work happens in a background task, nobody is told. The application then behaves exactly like one that is broken.

What you see

  • The setting saved without complaint, so the credentials look accepted.
  • Pressing the button reports something reassuring: "Learning the tag vocabulary in the background."
  • Nothing is ever produced — no tags, no related items, no matches.
  • Your provider dashboard shows zero usage, as though no request was ever made.
  • A preview or test screen says you need to build the vocabulary first — which is what it also says to somebody who has never pressed the button at all.
  • The AdminCP support tool reports no problems, correctly, because there is no longer anything to report.

That last point is the one that wastes the afternoon. Every signal available to the admin says the system is fine.

The fix

Use an embeddings model. For OpenAI, text-embedding-3-small. For Voyage, voyage-3.5-lite. Then run the vocabulary build again — the old attempt stored nothing, so there is nothing to clean up.

Chat models and embeddings models are not interchangeable in either direction. A chat model returns generated text; an embeddings model returns a vector. Code that expects one cannot use the other, and the endpoints are separate URLs.

Why it goes quiet — for developers

This is worth understanding if you build applications for Invision Community, because the trap is in the queue contract rather than in anyone's API client.

A job that cannot succeed has exactly one way to stop itself: throw OutOfRangeException. But that exception does not mean "I failed" — it means "I am finished, remove me from the queue." So the natural-looking error handler destroys its own evidence:

try
{
    $done = Vocabulary::embed( $slice );
}
catch ( \Throwable $e )
{
    Log::log( $e, 'my_app' );   // the only trace, and nobody reads it

    throw new OutOfRangeException; // "finished" - the row is deleted
}

The row is gone, so the AdminCP has nothing pending to show, and the support tool is right to say there are no problems. The reason survives only in the system log, which no admin has any cue to open.

Two things fix it, and they are worth doing together:

  • Persist the reason where the interface can find it — a setting, a column, anything that outlives the job. Then show it on your own settings screen, quoting the provider verbatim. "You tried to use a chat model in the embeddings endpoint" diagnoses itself when an admin can actually read it.
  • Validate at the point of entry. Send one short test string with the provider, key and model the admin just typed, before saving, and refuse the save with the provider's own wording if it fails. A model name is free text; there is no way for the admin to know it is wrong, and half an hour later in a background task is the worst possible moment to find out.

Also make sure "not configured yet" and "the last attempt failed" are different messages. If they are the same string, you are telling somebody who just pressed the button to press the button.

A note on how this was found

It took four exchanges with the customer to identify, and the first three answers were confidently wrong — scheduled tasks, the queue, the cron. The model name only came up because the customer mentioned it themselves. If a feature calls an external API and reports no activity at all, ask which model and which key are configured before discussing anything else. A model meant for a different endpoint produces exactly the symptoms of a job that never ran.



User Feedback

Recommended Comments

There are no comments to display.

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.