{"record":{"id":"191ba3fbe402f698","repo":"gitroomhq/postiz-app","slug":"all-posts-must-have-an-integration-id","errorCode":null,"errorMessage":"All posts must have an integration id","messagePattern":"All posts must have an integration id","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts","lineNumber":254,"sourceCode":"  async getStatistics(orgId: string, id: string) {\n    const getPost = await this.getPostsRecursively(id, true, orgId, true);\n    const content = getPost.map((p) => p.content);\n    const shortLinksTracking = await this._shortLinkService.getStatistics(\n      content\n    );\n\n    return {\n      clicks: shortLinksTracking,\n    };\n  }\n\n  async mapTypeToPost(\n    body: CreatePostDto,\n    organization: string,\n    replaceDraft: boolean = false\n  ): Promise<CreatePostDto> {\n    if (!body?.posts?.every((p) => p?.integration?.id)) {\n      throw new BadRequestException('All posts must have an integration id');\n    }\n\n    const mappedValues = {\n      ...body,\n      type: replaceDraft ? 'schedule' : body?.type,\n      posts: await Promise.all(\n        body?.posts?.map(async (post) => {\n          const integration = await this._integrationService.getIntegrationById(\n            organization,\n            post.integration.id\n          );\n\n          if (!integration) {\n            throw new BadRequestException(\n              `Integration with id ${post.integration.id} not found`\n            );\n          }\n","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts#L236-L272","documentation":"PostsService.mapTypeToPost requires every entry in body.posts to carry an integration.id before it can map a submitted post to persisted posts. The integration id identifies which connected social channel the post targets; without it the post cannot be routed to a provider.","triggerScenarios":"POST /organization/:orgId/posts (createPost) or a draft replace where body.posts contains an item with a missing or null integration, or the posts array itself is undefined (every() on undefined short-circuits the guard via optional chaining and fails).","commonSituations":"Client sends { posts: [{ content: 'hi' }] } without selecting a channel; integration object dropped by a form state bug; API consumers building payloads manually and omitting integration; draft payloads where integration was not persisted.","solutions":["Ensure every item in posts[] includes the id of a connected integration (e.g. posts: [{ integration: { id: '<integrationId>' }, content: '...' }])","Validate the payload client-side before submitting: posts.every(p => p?.integration?.id)","If the integration was deleted, re-connect the channel to get a new integration id and resubmit","Check the CreatePostDto parsing if a custom client strips unknown properties such as integration"],"exampleFix":"// before\n{ type: 'schedule', posts: [{ content: 'Hello' }] }\n// after\n{ type: 'schedule', posts: [{ integration: { id: integrationId }, content: 'Hello' }] }","handlingStrategy":"validation","validationCode":"const ok = body?.posts?.length > 0 && body.posts.every((p) => p?.integration?.id);\nif (!ok) throw new Error('Select a channel for every post variant');","typeGuard":"const hasIntegrationIds = (b: CreatePostDto): boolean =>\n  Array.isArray(b?.posts) && b.posts.length > 0 && b.posts.every((p) => !!p?.integration?.id);","tryCatchPattern":null,"preventionTips":["Require a channel selection in the composer before enabling save","Disable the submit button until every variant has an integration","Log the payload shape when the 400 arrives to spot stripped fields"],"tags":["posts","validation","integration","dto"],"backgroundTag":"missing-required-field","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}