langgenius/dify · error · AppUnavailableError
app_unavailable
app_unavailable
Error message
App unavailable, please check your app configurations.
What it means
Raised as AppUnavailableError (error_code app_unavailable, HTTP 400) at the top of ChatAudioApi.post in explore/audio.py (POST /installed-apps/<installed_app_id>/audio-to-text). When installed_app.app_with_session returns None the underlying App is gone, so there is nothing to run speech-to-text against. AppUnavailableError's fixed description is 'App unavailable, please check your app configurations.'
Source
Thrown at api/controllers/console/explore/audio.py:56
from .. import console_ns
logger = logging.getLogger(__name__)
register_schema_model(console_ns, TextToAudioPayload)
register_response_schema_models(console_ns, AudioBinaryResponse, AudioTranscriptResponse)
@console_ns.route(
"/installed-apps/<uuid:installed_app_id>/audio-to-text",
endpoint="installed_app_audio",
)
class ChatAudioApi(InstalledAppResource):
@console_ns.response(200, "Success", console_ns.models[AudioTranscriptResponse.__name__])
def post(self, installed_app: InstalledApp):
app_model = installed_app.app_with_session(session=db.session())
if app_model is None:
raise AppUnavailableError()
file = request.files["file"]
try:
response = AudioService.transcript_asr(
app_model=app_model,
file=file,
session=db.session(),
end_user=None,
)
return response
except services.errors.app_model_config.AppModelConfigBrokenError:
logger.exception("App model config broken.")
raise AppUnavailableError()
except NoAudioUploadedServiceError:
raise NoAudioUploadedError()
except AudioTooLargeServiceError as e:View on GitHub (pinned to ef8544b173)
Solutions
- Verify the installed_app_id still points to a live App (re-list installed apps).
- Reinstall the app from the explore marketplace if the source was removed.
- On the client, treat app_unavailable as 'app deleted, refresh'.
- Confirm the authenticated account can access the app's tenant.
Example fix
// before POST /installed-apps/<installed-app-id>/audio-to-text // app deleted -> 400 app_unavailable // after installed = await GET /installed-apps // pick a live one POST /installed-apps/<installed[0].id>/audio-to-text
Defensive patterns
Strategy: validation
Validate before calling
async function audioToText(installedAppId) {
const installed = await fetch(`/installed-apps`).then(r => r.json());
const entry = (installed.items ?? []).find(i => i.id === installedAppId && i.app);
if (!entry) throw new Error('app_unavailable');
return fetch(`/installed-apps/${installedAppId}/audio-to-text`, { method: 'POST', body: formData });
} Type guard
function isLiveInstalledApp(entry) { return !!entry && !!entry.app; } Try / catch
try { await audioToText(id); } catch (e) { if (e.code === 'app_unavailable') { refreshInstalledApps(); return; } throw e; } Prevention
- Re-list installed apps before calling.
- Reinstall the app if its source was deleted.
- Treat app_unavailable as 'app deleted, refresh'.
When it happens
Trigger: Calling the installed-app audio endpoint after the App referenced by the InstalledApp was deleted or could not be loaded. The `if app_model is None` guard fires immediately and raises.
Common situations: Installed app whose source app was removed; app soft-deleted but installed-app record remains; tenant/app scope mismatch on the session; exploring a stale installed-app link.
Related errors
- no_audio_uploaded
- no_audio_uploaded
- provider_not_support_speech_to_text
- speech_to_text_disabled
- audio_too_large
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/0d8b44dd1ddc0d6f.
Report an issue: GitHub.