calcom/cal.diy · warning · Error
Already installed
Error message
Already installed
What it means
Thrown from Alby's 'add' handler when a credential row with the Alby app type already exists for the current user. Alby supports only one credential per user, so re-running the install flow is rejected. The throw is caught by the surrounding try/catch and converted by getServerErrorFromUnknown into the HTTP response.
Source
Thrown at packages/app-store/alby/api/add.ts:21
import { getServerErrorFromUnknown } from "@calcom/lib/server/getServerErrorFromUnknown";
import prisma from "@calcom/prisma";
import config from "../config.json";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (!req.session?.user?.id) {
return res.status(401).json({ message: "You must be logged in to do this" });
}
const appType = config.type;
try {
const alreadyInstalled = await prisma.credential.findFirst({
where: {
type: appType,
userId: req.session.user.id,
},
});
if (alreadyInstalled) {
throw new Error("Already installed");
}
const installation = await prisma.credential.create({
data: {
type: appType,
key: {},
userId: req.session.user.id,
appId: "alby",
},
});
if (!installation) {
throw new Error("Unable to create user credential for Alby");
}
} catch (error: unknown) {
const httpError = getServerErrorFromUnknown(error);
return res.status(httpError.statusCode).json({ message: httpError.message });
}
View on GitHub (pinned to 176037d0af)
Solutions
- Uninstall the existing Alby credential first, then retry the install.
- Detect the existing credential on the client and route the user straight to /apps/alby/setup.
- In dev, remove the row: prisma.credential.deleteMany({ where: { type: <appType>, userId } }).
- Treat the 'Already installed' message in the UI as a redirect, not a hard error.
Example fix
// before
if (alreadyInstalled) {
throw new Error('Already installed');
}
// after
if (alreadyInstalled) {
return res.status(200).json({ url: '/apps/alby/setup' });
} Defensive patterns
Strategy: validation
Validate before calling
const existing = await prisma.credential.findFirst({
where: { type: appType, userId },
});
if (existing) {
// route to setup instead of re-running add
} Type guard
const isAlreadyInstalledError = (e: unknown) => e instanceof Error && e.message === 'Already installed';
Try / catch
try {
await fetch('/api/integrations/alby/add').then((r) => r.json());
} catch (e) {
if (isAlreadyInstalledError(e)) {
router.push('/apps/alby/setup');
} else throw e;
} Prevention
- Check for an existing credential before offering the install button.
- Treat 'Already installed' as a redirect, not a failure.
- Idempotently delete the credential before re-installing in dev.
When it happens
Trigger: User clicks 'Install Alby' a second time while a credential row already exists; the install flow was interrupted and re-triggered; a previous uninstall left the credential behind.
Common situations: Stale credential after a failed uninstall; dev seed data with a pre-existing alby credential; double-click on the install button; race where two install requests fire concurrently.
Related errors
- Unable to create user credential for Alby
- Credentials not found
- Credentials not valid
- Email already exists
- Google Meet is already connected for this user.
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/006a36a66d09ff1d.
Report an issue: GitHub.