{"record":{"id":"6cce5b8b6d7e61b5","repo":"Dokploy/dokploy","slug":"bad-request-6cce5b","errorCode":"BAD_REQUEST","errorMessage":"Provide a config or a vaultProviderId to test","messagePattern":"Provide a config or a vaultProviderId to test","errorType":"exception","errorClass":"TRPCError","httpStatus":400,"severity":"warning","filePath":"apps/dokploy/server/api/routers/vault-provider.ts","lineNumber":106,"sourceCode":"\t\t\tconfig: maskVaultProviderConfig(provider.config),\n\t\t}));\n\t}),\n\n\tone: withPermission(\"vaultProvider\", \"read\")\n\t\t.input(apiFindOneVaultProvider)\n\t\t.query(async ({ ctx, input }) => {\n\t\t\tconst provider = await findVaultProviderInOrganization(\n\t\t\t\tinput.vaultProviderId,\n\t\t\t\tctx.session.activeOrganizationId,\n\t\t\t);\n\t\t\treturn { ...provider, config: maskVaultProviderConfig(provider.config) };\n\t\t}),\n\n\ttestConnection: withPermission(\"vaultProvider\", \"create\")\n\t\t.input(apiTestVaultProvider)\n\t\t.mutation(async ({ ctx, input }) => {\n\t\t\tif (!input.config && !input.vaultProviderId) {\n\t\t\t\tthrow new TRPCError({\n\t\t\t\t\tcode: \"BAD_REQUEST\",\n\t\t\t\t\tmessage: \"Provide a config or a vaultProviderId to test\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet config = input.config;\n\t\t\tif (input.vaultProviderId) {\n\t\t\t\tconst provider = await findVaultProviderInOrganization(\n\t\t\t\t\tinput.vaultProviderId,\n\t\t\t\t\tctx.session.activeOrganizationId,\n\t\t\t\t);\n\t\t\t\tconfig = config\n\t\t\t\t\t? mergeVaultProviderConfig(config, provider.config)\n\t\t\t\t\t: provider.config;\n\t\t\t}\n\n\t\t\tawait testVaultProviderConnection(config!);\n\t\t\treturn true;","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/Dokploy/dokploy/blob/546686ea3587f12ec5652217dedd9f7960fb6d15/apps/dokploy/server/api/routers/vault-provider.ts#L88-L124","documentation":"Thrown by Dokploy's vault-provider testConnection mutation when the input contains neither an inline config object nor a vaultProviderId. The endpoint can test a draft configuration (config) or an already-saved provider (vaultProviderId), and requires at least one.","triggerScenarios":"Calling testConnection with {} or with both config and vaultProviderId absent — e.g. a 'Test connection' button clicked before any form fields were filled and no saved provider selected.","commonSituations":"UI submitting the test before form state hydrates; conditional form where the saved-provider select and the manual config fields are both empty; API consumers assuming testConnection defaults to some provider.","solutions":["Pass the full provider config object from the form, or the id of an existing saved vault provider","Disable the Test button until one of the two is present","Validate client-side before calling the mutation"],"exampleFix":"// before\nawait trpc.vaultProvider.testConnection.mutate({ projectId, environmentId });\n\n// after\nawait trpc.vaultProvider.testConnection.mutate({\n  projectId,\n  environmentId,\n  config: { provider: 'hashicorp-vault', url, token, ... },\n});","handlingStrategy":"validation","validationCode":"if (form.config || selectedProviderId) {\n  await trpc.vaultProvider.testConnection.mutate({\n    projectId, environmentId,\n    config: form.config ?? undefined,\n    vaultProviderId: selectedProviderId ?? undefined,\n  });\n}","typeGuard":"const canTest = (i: { config?: unknown; vaultProviderId?: string }) =>\n  Boolean(i.config) || Boolean(i.vaultProviderId);","tryCatchPattern":"catch (e) { if (e?.data?.code === 'BAD_REQUEST') highlightEmptyForm(); else throw e; }","preventionTips":["Disable the Test button until config or provider is chosen","Clear stale providerId when switching to manual config mode","Validate the payload client-side with the same zod schema"],"tags":["dokploy","trpc","vault","bad-request","validation"],"backgroundTag":"missing-required-parameter","analyzedSha":"546686ea3587f12ec5652217dedd9f7960fb6d15","analyzedAt":"2026-08-27T05:18:58.095Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}