Consistently getting the "resource already exists" error even on a new org/account

I have one service in a multi-service monorepo, that consistently fails, even when I’ve deep cleaned out all the resources and fully deleted everything and started from fresh. I think it’s very similar to this error: Keep getting error - <resource> already exist but I don’t know enough about serverless file syntax to know what I’m accidentally double declaring.

Additional context is that this appears to work on my colleague’s computer, but not mine. I am running the latest version of framework core (2.2.0) and I am not sure what he is running, so this is potentially something where the latest version infers a resource creation which would not have been inferred in a previous one. The resource specifically that is failing is “MailsBucket”.

This is the content of this serverless file, with the service name redacted:

service:
  name: [xxxxxx]

package:
  exclude:
    - '**/node_modules/aws-sdk/**'
    - '**/node_modules/@types/**'

custom:
  build: npm run ${env:SLS_BUILD, 'build'}

  scriptHooks:
    'deploy:function:initialize': ${self:custom.build}
    'package:initialize': ${self:custom.build}
    'invoke:local:loadEnvVars': ${self:custom.build}
    'after:deploy:finalize': build/ses-dest-add.js

  stage: ${opt:stage, env:STAGE, self:provider.stage}

  region: ${opt:region, env:AWS_REGION, self:provider.region}

  sendingEnabled:
    prod: true
    dev: false

  sesRulesEnabled:
    prod: true
    dev: true

#  dotenv:
#    logging: false

  queue:
    name: ${self:service}-emails-send-${self:custom.stage}
    arn: { Ref: MailsQueue }

  bucket:
    name: ${self:service}-${self:custom.stage}
    prefix: mailtumble-incoming-emails

  configSet: ${self:service}-email-info-${self:custom.stage}

  statTopic:
    name: ${self:service}-stat-${self:custom.stage}
    arn: { Ref: StatTopic }

  table:
    name:
      Fn::ImportValue: { Fn::Join : [ '-', [ '[xxxxxx]-next-core', '${self:custom.stage}', 'table' ] ] }
    arn:
      Fn::ImportValue: { Fn::Join : [ '-', [ '[xxxxxx]-next-core', '${self:custom.stage}', 'table-arn' ] ] }

  remover:
    buckets:
      - ${self:custom.bucket.name}

plugins:
  - serverless-scriptable-plugin
  - serverless-dotenv-plugin
  - serverless-export-env
  - serverless-s3-remover

provider:
  name: aws

  runtime: nodejs12.x

  memorySize: 128

  environment:
    DEFAULT_DOMAIN: ${env:DEFAULT_DOMAIN}
    FROM_EMAIL: ${env:FROM_EMAIL}
    TABLE: ${self:custom.table.name}
    TABLE_ARN: ${self:custom.table.arn}
    MAILS_QUEUE: ${self:custom.queue.name}
    MAILS_QUEUE_URL: ${self:custom.queue.arn}
    MAILS_BUCKET: ${self:custom.bucket.name}
    MAILS_BUCKET_PREFIX: ${self:custom.bucket.prefix}
    SEND_EMAIL_CONFIG_SET: ${self:custom.configSet}
    STAT_TOPIC: ${self:custom.statTopic.name}
    STAT_TOPIC_ARN: ${self:custom.statTopic.arn}

  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource:
        - ${self:custom.table.arn}
        - { Fn::Join : [ '', [ '${self:custom.table.arn}', '/index/*' ] ] }

    - Effect: Allow
      Action:
        - s3:GetObject
        - s3:GetObjectAcl
      Resource: { Fn::Join : [ '', [ { Fn::GetAtt: ['MailsBucket', 'Arn'] }, '/*' ] ] }

    - Effect: Allow
      Action:
        - sqs:GetQueueAttributes
        - sqs:SendMessage
        - sqs:DeleteMessage
        - sqs:ReceiveMessage
      Resource: { Fn::GetAtt: ['MailsQueue', 'Arn']  }

    - Effect: Allow
      Action:
        - ses:SendEmail
        - ses:SendRawEmail
      Resource: '*'

functions:

  ProcessIncoming:
    handler: dist/handler/incoming/incoming.handle

  SendEmails:
    handler: dist/handler/send/send.handle
    timeout: 120
    memorySize: 256
    events:
      - schedule:
          rate: rate(1 minute)
          enabled: ${self:custom.sendingEnabled.${self:custom.stage}, self:custom.sendingEnabled.dev}

  UpdateSendingStat:
    handler: dist/handler/stat/stat.handle
    memorySize: 256
    events:
      - sns:
          arn: ${self:custom.statTopic.arn}
          topicName: ${self:custom.statTopic.name}

resources:
  Resources:
    # --------------------------------------------------------------------
    # Resources
    # --------------------------------------------------------------------

    # S3 Bucket to save emails

    MailsBucket:
      Type: AWS::S3::Bucket
      DeletionPolicy: Delete
      Properties:
        BucketName: ${self:custom.bucket.name}
        LifecycleConfiguration:
          Rules:
            - Id: DeleteOldEmails
              Status: Enabled
              ExpirationInDays: 365
              Prefix: ${self:custom.bucket.prefix}

    # Queue for messages to send

    MailsQueue:
      Type: AWS::SQS::Queue
      Properties:
        QueueName: ${self:provider.environment.MAILS_QUEUE}
        MessageRetentionPeriod: 1209600
        VisibilityTimeout: 60

    # SNS topic for SES to send email sending stat (bounces, complains and etc)
    StatTopic:
      Type: AWS::SNS::Topic
      Properties:
        TopicName: ${self:custom.statTopic.name}

    # --------------------------------------------------------------------
    # Permissions
    # --------------------------------------------------------------------

    # Allows SES to call process incoming lambda

    MailtumbleSESProcessIncomingLambdaFunctionPermission:
      Type: AWS::Lambda::Permission
      Properties:
        FunctionName: { 'Fn::GetAtt': ['ProcessIncomingLambdaFunction', 'Arn'] }
        Principal: ses.amazonaws.com
        Action: 'lambda:InvokeFunction'
        SourceAccount: { Ref: AWS::AccountId }

    # Allows SES to save emails in S3 bucket

    [xxxxxx]SESMailsBucketPermissions:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket:
          Ref: MailsBucket
        PolicyDocument:
          Statement:
            - Principal:
                Service: ses.amazonaws.com
              Action:
                - s3:PutObject
              Effect: Allow
              Sid: AllowSESPuts
              Resource:
                Fn::Join:
                  ['', ['arn:aws:s3:::', Ref: 'MailsBucket', '/*']]
              Condition:
                StringEquals:
                  'aws:Referer': { Ref: AWS::AccountId }

    # --------------------------------------------------------------------
    # SES Rules
    # --------------------------------------------------------------------

    # Incoming email triggers (works when email sent to DEFAULT_DOMAIN)

    ProcessIncomingRule:
      Type: AWS::SES::ReceiptRule
      DependsOn:
        - MailtumbleSESMailsBucketPermissions
        - MailtumbleSESProcessIncomingLambdaFunctionPermission
      Properties:
        RuleSetName: default-rule-set
        Rule:
          Name: ${self:service}-process-incoming-${self:custom.stage}
          Enabled: ${self:custom.sesRulesEnabled.${self:custom.stage}, self:custom.sesRulesEnabled.dev}
          ScanEnabled: true
          Recipients:
            - ${self:provider.environment.DEFAULT_DOMAIN}
            - ${self:provider.environment.FROM_EMAIL}
          Actions:
            - S3Action:
                BucketName: ${self:custom.bucket.name}
                ObjectKeyPrefix: ${self:custom.bucket.prefix}
            - LambdaAction:
                FunctionArn:
                  { 'Fn::GetAtt': ['ProcessIncomingLambdaFunction', 'Arn'] }
                InvocationType: Event

    # Outgoing rules (working when sending email using SES)

    # Cloudformation doesn't allow to use SNS as EventDestination check
    # build/ses-dest-add.js for manually adding it via API

    SendToSNSConfigSet:
      Type: AWS::SES::ConfigurationSet
      Properties:
        Name: ${self:custom.configSet}