badges/shields · error · NotFound
no packages found
Error message
no packages found
What it means
The F-Droid service fetches package metadata and filters json.packages down to entries whose versionCode is at or below the suggestedVersionCode (when one is present). If no packages remain after filtering, it throws NotFound with prettyMessage 'no packages found', meaning F-Droid reports no usable package builds for this app.
Source
Thrown at services/f-droid/f-droid.service.js:78
baseUrl = baseUrl.replace(/\/$/, '')
const url = `${baseUrl}/api/v1/packages/${appId}`
return this._requestJson({
schema,
url,
httpErrors: {
403: 'app not found',
404: 'app not found',
},
})
}
transform({ json, suggested }) {
const svc = suggested && json.suggestedVersionCode
const packages = (json.packages || []).filter(
({ versionCode }) => !svc || versionCode <= svc,
)
if (packages.length === 0) {
throw new NotFound({ prettyMessage: 'no packages found' })
}
const version = packages.reduce((a, b) =>
a.versionCode > b.versionCode ? a : b,
).versionName
return { version }
}
async handle(
{ appId },
{ baseUrl = 'https://f-droid.org', include_prereleases: includePre },
) {
const json = await this.fetch({ baseUrl, appId })
const suggested = includePre === undefined
const { version } = this.transform({ json, suggested })
return renderVersionBadge({ version })
}
}
View on GitHub (pinned to 766fd8bc89)
Solutions
- Verify the app id in the F-Droid index and confirm it has published packages
- Check the F-Droid index JSON for the app to see whether packages is empty or filtered out by suggestedVersionCode
- Pin/choose a different F-Droid mirror or index that includes the builds
- Wait for F-Droid to publish a build within the suggested version range
Example fix
// before /badge/f-droid/v/org.fdroid.wrongid // after /badge/f-droid/v/org.fdroid.fdroid
Defensive patterns
Strategy: validation
Validate before calling
async function fdroidHasPackages(appId) {
const res = await fetch(`https://f-droid.org/api/v1/packages/${appId}`)
if (!res.ok) return false
const json = await res.json()
return Array.isArray(json.packages) && json.packages.length > 0
}
// verify before rendering the badge Type guard
function hasPackages(json) {
return Array.isArray(json.packages) && json.packages.length > 0
} Try / catch
try {
const badge = await getFDroidVersionBadge(appId)
} catch (e) {
if (e.prettyMessage === 'no packages found') {
renderPlaceholderBadge('not published')
} else throw e
} Prevention
- Confirm the exact F-Droid app id (package name) before configuring the badge
- Check the F-Droid index JSON for the app to confirm packages exist within the suggested version range
- Expect this error for freshly published or fully archived apps
- Monitor badge health so schema/index changes surface quickly
When it happens
Trigger: Requesting an F-Droid version badge for an app whose packages array is empty or whose packages all have versionCodes above suggestedVersionCode (e.g. all builds marked unstable/newer than suggested).
Common situations: Newly published apps with no package builds yet; apps where every package was archived or is a pre-release above the suggested version; typos in the app id returning a metadata stub with no packages.
Related errors
AI-assisted analysis of badges/shields@766fd8bc89 (2026-08-30).
Data as JSON: /api/errors/bffe7dbe7d8a0a8d.
Report an issue: GitHub.