Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 4, 2025

  • Understand the issue: _TypeError (type '_Set<ParseObject>' is not a subtype of type 'Set<Contact>' in type cast) when calling addRelation with custom ParseObject subclasses
  • Identify the root cause: In parse_relation.dart line 93, knownObjects = lastPreformedOperation!.value.toSet() as Set<T>; casts a Set<ParseObject> to Set<T> which fails for subclasses when getRelation<T>() was called first
  • Create a failing test that reproduces the issue
  • Implement the fix: Change knownObjects from Set<T> to Set<ParseObject> and remove the unsafe cast
  • Verify all tests pass (28 relation tests, 157 total)
  • Fix lint issues (format test file)
Original prompt

This section details on the original issue you should resolve

<issue_title>_TypeError on addRelation</issue_title>
<issue_description>### New Issue Checklist

Issue Description

Having:

Order Class

class Order extends ParseObject implements ParseCloneable {
  Order() : super(_keyTableName);
  Order.clone() : this();

  @override
  clone(Map map) => Order.clone()..fromJson(Map<String, dynamic>.from(map));

  static const String _keyTableName = 'Order';
  static const String keyInitialProduct = 'initial_product';
  static const String keyProduct = 'product';
  static const String keyPrice = 'price';
  static const String keyCertainDate = 'certain_date';
  static const String keyState = 'state';
  static const String keyAccount = 'account';


  Product? get initialProduct => get(keyInitialProduct);
  set initialProduct(Product? initialProduct) =>
      set(keyInitialProduct, initialProduct);

  Product? get product => get(keyProduct);
  set product(Product? product) => set(keyProduct, product);

  Account? get account => get(keyAccount);
  set account(Account? account) => set(keyAccount, account);

  DateTime? get certainDate => get<DateTime?>(keyCertainDate);
  set certainDate(DateTime? certainDate) =>
      set<DateTime?>(keyCertainDate, certainDate);

}

Order Schema

{
  "className": "Order",
  "fields": {
    "objectId": {
      "type": "String"
    },
    "createdAt": {
      "type": "Date"
    },
    "updatedAt": {
      "type": "Date"
    },
    "ACL": {
      "type": "ACL"
    },
    "initial_product": {
      "type": "Pointer",
      "targetClass": "Product",
      "required": false
    },
    "receivers": {
      "type": "Relation",
      "targetClass": "Contact",
      "required": false
    },
    "price": {
      "type": "Number",
      "required": false
    },
    "certain_date": {
      "type": "Date",
      "required": false
    },
    "state": {
      "type": "String",
      "required": true,
      "defaultValue": "draft"
    },
    "account": {
      "type": "Pointer",
      "targetClass": "Account",
      "required": true
    },
    "product": {
      "type": "Pointer",
      "targetClass": "Product",
      "required": false
    }
  },
  "classLevelPermissions": {
    "find": {
      "*": true
    },
    "count": {
      "*": true
    },
    "get": {
      "*": true
    },
    "create": {
      "*": true
    },
    "update": {
      "*": true
    },
    "delete": {
      "*": true
    },
    "addField": {
      "*": true
    },
    "protectedFields": {
      "*": []
    }
  },
  "indexes": {
    "_id_": {
      "_id": 1
    }
  }
}

Contact class

class Contact extends ParseObject implements ParseCloneable {
  Contact() : super(_keyTableName);
  Contact.clone() : this();

  /// Mimic a clone due to Flutter not using reflection
  @override
  clone(Map map) => Contact.clone()..fromJson(Map<String, dynamic>.from(map));

  static const String _keyTableName = 'Contact';
  static const String keyName = 'name';
  static const String keyPhone = 'phone';
  static const String keyAddress = 'address';
  static const String keyBirthday = 'birthday';
  static const String keyAccount = 'account';

  String? get name => get<String?>(keyName);
  set name(String? name) => set<String?>(keyName, name);

  String? get phone => get<String?>(keyPhone);
  set phone(String? phone) => set<String?>(keyPhone, phone);

  String? get address => get<String?>(keyAddress);
  set address(String? address) => set<String?>(keyAddress, address);

  DateTime? get birthday => get<DateTime?>(keyBirthday);
  set birthday(DateTime? birthday) => set<DateTime?>(keyBirthday, birthday);

  Account? get account => get<Account?>(keyAccount);
  set account(Account? account) => set<Account?>(keyAccount, account);

}

Steps to reproduce

      List<Contact> contactsObjects = (result as Set)
          .map((key) => Contact()..objectId = key.value)
          .toList();

      var order = widget.order!;
      order.addRelation(...

</details>

- Fixes parse-community/Parse-SDK-Flutter#999

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for you](https://github.com/parse-community/Parse-SDK-Flutter/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.

@coderabbitai
Copy link

coderabbitai bot commented Dec 4, 2025

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands and usage tips.

@mtrezza mtrezza marked this pull request as ready for review December 4, 2025 08:42
Copilot AI changed the title [WIP] Fix TypeError on addRelation function Fix _TypeError on addRelation with custom ParseObject subclasses Dec 4, 2025
@mtrezza mtrezza changed the title Fix _TypeError on addRelation with custom ParseObject subclasses fix: TypeError on addRelation function Dec 4, 2025
@parse-github-assistant
Copy link

🚀 Thanks for opening this pull request!

Copilot AI requested a review from mtrezza December 4, 2025 08:43
@codecov
Copy link

codecov bot commented Dec 4, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 43.96%. Comparing base (76eeca4) to head (121d790).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1098   +/-   ##
=======================================
  Coverage   43.96%   43.96%           
=======================================
  Files          61       61           
  Lines        3596     3596           
=======================================
  Hits         1581     1581           
  Misses       2015     2015           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mtrezza
Copy link
Member

mtrezza commented Dec 4, 2025

@copilot fix the lint issues in CI

Copy link
Contributor Author

Copilot AI commented Dec 4, 2025

@copilot fix the lint issues in CI

Fixed in 121d790. The test file formatting has been corrected with dart format.

@mtrezza mtrezza merged commit f284944 into master Dec 4, 2025
14 of 24 checks passed
parseplatformorg pushed a commit that referenced this pull request Dec 4, 2025
# [dart-v9.4.6](dart-9.4.5...dart-9.4.6) (2025-12-04)

### Bug Fixes

* TypeError on `addRelation` function ([#1098](#1098)) ([f284944](f284944))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version dart-v9.4.6

@mtrezza mtrezza linked an issue Dec 4, 2025 that may be closed by this pull request
@mtrezza mtrezza mentioned this pull request Dec 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

_TypeError on addRelation

3 participants