{"record":{"id":"210a501762b2303a","repo":"yikart/AiToEarn","slug":"channelplatformoperationnotsupported-210a50","errorCode":"ChannelPlatformOperationNotSupported","errorMessage":"ChannelPlatformOperationNotSupported","messagePattern":"ChannelPlatformOperationNotSupported","errorType":"error_code","errorClass":"AppException","httpStatus":null,"severity":"warning","filePath":"project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/threads/threads-publish-options.provider.ts","lineNumber":38,"sourceCode":"\n@Injectable()\nexport class ThreadsPublishOptionsProvider implements PublishOptionSourceProvider {\n  constructor(private readonly threadsService: ThreadsService) {}\n\n  listSources() {\n    return [{\n      field: 'location_id',\n      label: 'Location',\n      description: 'Threads post location',\n      valueType: PublishOptionValueType.List,\n      requiresAccount: true,\n      filterSchema: ThreadsLocationFilterSchema,\n    }]\n  }\n\n  async getValues(input: PublishOptionValuesInput): Promise<PublishOptionValuesResult> {\n    if (input.field !== 'location_id') {\n      throw new AppException(ResponseCode.ChannelPlatformOperationNotSupported, {\n        platform: AccountType.Threads,\n        field: input.field,\n      })\n    }\n\n    const filters = ThreadsLocationFilterSchema.parse(input.filters ?? {})\n    const locations = await this.threadsService.searchLocations(\n      input.credential.accessToken,\n      filters,\n    )\n\n    return {\n      field: 'location_id',\n      valueType: PublishOptionValueType.List,\n      items: locations\n        .filter(location => Boolean(location.id))\n        .map(location => ({\n          value: location.id,","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/threads/threads-publish-options.provider.ts#L20-L56","documentation":"Threads publish-options only implements value lookup for the 'location_id' field; any other field key passed to getValues is rejected with ChannelPlatformOperationNotSupported naming Threads and the offending field. It is an unsupported-operation guard, not a data error.","triggerScenarios":"Calling getValues with input.field set to anything other than 'location_id' (e.g. 'topic_id', 'mentioned_user_id') for the Threads provider.","commonSituations":"Generic option-refresh UI iterating all registered filter fields for every platform and hitting Threads with fields it doesn't support; a newly added filter schema field without a corresponding getValues branch; client/platform mismatch after adding a shared field.","solutions":["Only request option values for field='location_id' on the Threads platform.","Filter the platform's supported fields (see the getSchema/filterSchema definitions above getValues) before calling getValues.","If a new field is genuinely needed, extend getValues with a branch implementing that field's lookup rather than reusing location_id's path.","Update the caller to handle ChannelPlatformOperationNotSupported as 'field unsupported' and skip the field gracefully."],"exampleFix":"// before\nfor (const field of ['location_id', 'topic_id']) {\n  await provider.getValues({ field, filters })\n}\n// after\nfor (const field of ['location_id']) { // Threads supports location_id only\n  await provider.getValues({ field, filters })\n}","handlingStrategy":"type-guard","validationCode":"const THREADS_SUPPORTED_FIELDS = ['location_id'] as const\nfunction threadsSupportsField(field: string): boolean {\n  return (THREADS_SUPPORTED_FIELDS as readonly string[]).includes(field)\n}","typeGuard":"function isThreadsOptionField(field: string): field is 'location_id' {\n  return field === 'location_id'\n}","tryCatchPattern":"try {\n  await provider.getValues({ field, filters })\n} catch (e) {\n  if (e instanceof AppException && e.code === ResponseCode.ChannelPlatformOperationNotSupported) {\n    return { values: [], supported: false } // skip unsupported field\n  }\n  throw e\n}","preventionTips":["Derive the caller's field list from each platform's schema instead of a shared hardcoded list.","Expose supported fields via a capability/method on the provider.","Treat ChannelPlatformOperationNotSupported as a benign skip in generic UIs.","Add tests covering every field each platform's schema declares."],"tags":["unsupported-operation","threads","options"],"backgroundTag":"unsupported-operation","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}