Assistance Needed with Motoko Code Deployment Issue

Dear DFINITY Support Team,

I hope this message finds you well.

I am currently encountering an issue with deploying a Motoko codebase on the Internet Computer platform, and I would greatly appreciate your assistance in resolving it.

The specific problem I am facing involves errors related to asynchronous function return types and misplaced await statements. Despite several attempts to correct the code, I continue to encounter the same errors.

import Trie "mo:base/Trie";
import Hash "mo:base/Hash";
import Principal "mo:base/Principal";
import Debug "mo:base/Debug";

actor MarriageBroker {
    // Define stable variables to store user profiles and partner preferences using Trie data structure.
    stable var userProfiles : Trie.Trie<Principal, UserProfile> = Trie.empty();
    stable var partnerPreferences : Trie.Trie<Principal, PartnerPreference> = Trie.empty();

    // Define the structure of a user profile.
    public type UserProfile = {
        name : Text;
        age : Nat;
        placeOfLiving : Text;
        country : Text;
        occupation : Text;
        salary : Nat;
        educationBackground : Text;
        imageUrl : Text;
    };

    // Define the structure of partner preferences.
    public type PartnerPreference = {
        ageRange : (Nat, Nat);
        placeOfLiving : Text;
        country : Text;
        occupation : Text;
        salaryRange : (Nat, Nat);
        educationBackground : Text;
    };

    // Function to add a user profile and their partner preferences.
    public shared({ caller }) func addUser(profile : UserProfile, preference : PartnerPreference) : async () {
        // Print debug message indicating addition of user.
        Debug.print("Adding user: " # Principal.toText(caller));
        
        // Store user profile in the userProfiles Trie.
        let callerKey = { hash = Principal.hash(caller); key = caller };
        let (newUserProfiles, _) = Trie.put(userProfiles, callerKey, Principal.equal, profile);
        userProfiles := newUserProfiles;
        
        // Store partner preferences in the partnerPreferences Trie.
        let (newPartnerPreferences, _) = Trie.put(partnerPreferences, callerKey, Principal.equal, preference);
        partnerPreferences := newPartnerPreferences;
        
        // Print debug message indicating successful addition of user.
        Debug.print("User added successfully.");
    };

    // Function to update a user's profile and partner preferences.
    public shared({ caller }) func updateUser(profile : UserProfile, preference : PartnerPreference) : async () {
        // Print debug message indicating update of user.
        Debug.print("Updating user: " # Principal.toText(caller));
        
        // Update user profile in the userProfiles Trie.
        let callerKey = { hash = Principal.hash(caller); key = caller };
        let (newUserProfiles, _) = Trie.put(userProfiles, callerKey, Principal.equal, profile);
        userProfiles := newUserProfiles;
        
        // Update partner preferences in the partnerPreferences Trie.
        let (newPartnerPreferences, _) = Trie.put(partnerPreferences, callerKey, Principal.equal, preference);
        partnerPreferences := newPartnerPreferences;
        
        // Print debug message indicating successful update of user.
        Debug.print("User updated successfully.");
    };

    // Function to get a user's profile.
    public shared({ caller }) func getUser(userId : Principal) : async ?UserProfile {
        // Print debug message indicating retrieval of user profile.
        Debug.print("Getting user: " # Principal.toText(userId));
        
        // Retrieve user profile from the userProfiles Trie.
        let userKey = { hash = Principal.hash(userId); key = userId };
        Trie.get(userProfiles, userKey, Principal.equal)
    };

    // Function to get a user's partner preferences.
    public shared({ caller }) func getPreference(userId : Principal) : async ?PartnerPreference {
        // Print debug message indicating retrieval of user's partner preferences.
        Debug.print("Getting preference for user: " # Principal.toText(userId));
        
        // Retrieve partner preferences from the partnerPreferences Trie.
        let userKey = { hash = Principal.hash(userId); key = userId };
        Trie.get(partnerPreferences, userKey, Principal.equal)
    };

    // Function to fetch a user's partner preferences asynchronously.
    public shared func fetchPreference(userId: Principal) : async?PartnerPreference {
        switch (getPreference(userId)) {
            case null {
                // If no preferences found, print debug message and return null.
                Debug.print("No preference found for user: " # Principal.toText(userId));
                return null;
            };
            case (?pref) { return pref; }; // Return the preferences.
        }
    };

    // Function to suggest profiles based on a user's partner preferences.
    public shared query({ caller }) func suggestProfiles(userId : Principal) : async [UserProfile] {
        // Print debug message indicating suggestion of profiles for a user.
        Debug.print("Suggesting profiles for user: " # Principal.toText(userId));
        
        // Fetch the user's preferences asynchronously.
        let preference = await fetchPreference(userId);

        switch (preference) {
            case null {
                // If no preferences found, print debug message and return an empty array.
                Debug.print("No preference found for user: " # Principal.toText(userId));
                return [];
            };
            case (?pref) {
                // If preferences found, iterate through userProfiles Trie to find matching profiles.
                var candidates : [UserProfile] = [];
                for ((_, profile) in userProfiles.iter()) {
                    if (matchPreference(profile, pref)) {
                        candidates := Array.append(candidates, [profile]);
                    };
                };
                // Print debug message indicating suggested profiles and return the candidates.
                Debug.print("Suggested profiles: " # debug_show(candidates));
                return candidates;
            };
        }
    };
}

Here is a summary of the issue:

  • Error Description: The deployment process fails with the following errors:
    • Type error [M0050]: Literal of type Null does not have expected type async<$fetchPreference> (?PartnerPreference)
      *** Type error [M0038]**: Misplaced await
  • Affected Code: The errors occur in the fetchPreference and suggestProfiles functions of the Motoko codebase.

Given the complexity of the errors and my efforts to troubleshoot them without success, I believe that expert guidance from your team would be invaluable in resolving this issue.

I have already attempted various adjustments to the code, including modifying return types and reorganizing switch statements. However, the errors persist.

I kindly request your assistance in diagnosing and resolving this issue. Any insights or suggestions you can provide would be greatly appreciated.

Thank you very much for your attention to this matter. I look forward to your prompt response and guidance on how to proceed.

Best regards,
najmul Haq

  1. Inside your fetchPreference fun, at switch statement you need to await for getPreference result.
  2. suggestProfiles function is a query call and inside that you are calling fetchPreference which is an update call, thats not allowed. You can only invoke update calls inside update functions.
2 Likes

I’m getting another error kindly request can you please help me

import Trie "mo:base/Trie";
import Hash "mo:base/Hash";
import Principal "mo:base/Principal";
import Debug "mo:base/Debug";



actor MarriageBroker {
    // Define stable variables to store user profiles and partner preferences using Trie data structure.
    stable var userProfiles : Trie.Trie<Principal, UserProfile> = Trie.empty();
    stable var partnerPreferences : Trie.Trie<Principal, PartnerPreference> = Trie.empty();

    // Define the structure of a user profile.
    public type UserProfile = {
        name : Text;
        age : Nat;
        placeOfLiving : Text;
        country : Text;
        occupation : Text;
        salary : Nat;
        educationBackground : Text;
        imageUrl : Text;
    };

    // Define the structure of partner preferences.
    public type PartnerPreference = {
        ageRange : (Nat, Nat);
        placeOfLiving : Text;
        country : Text;
        occupation : Text;
        salaryRange : (Nat, Nat);
        educationBackground : Text;
    };

    // Function to add a user profile and their partner preferences.
    public shared({ caller }) func addUser(profile : UserProfile, preference : PartnerPreference) : async () {
        // Print debug message indicating addition of user.
        Debug.print("Adding user: " # Principal.toText(caller));
        
        // Store user profile in the userProfiles Trie.
        let callerKey = { hash = Principal.hash(caller); key = caller };
        let (newUserProfiles, _) = Trie.put(userProfiles, callerKey, Principal.equal, profile);
        userProfiles := newUserProfiles;
        
        // Store partner preferences in the partnerPreferences Trie.
        let (newPartnerPreferences, _) = Trie.put(partnerPreferences, callerKey, Principal.equal, preference);
        partnerPreferences := newPartnerPreferences;
        
        // Print debug message indicating successful addition of user.
        Debug.print("User added successfully.");
    };

    // Function to update a user's profile and partner preferences.
    public shared({ caller }) func updateUser(profile : UserProfile, preference : PartnerPreference) : async () {
        // Print debug message indicating update of user.
        Debug.print("Updating user: " # Principal.toText(caller));
        
        // Update user profile in the userProfiles Trie.
        let callerKey = { hash = Principal.hash(caller); key = caller };
        let (newUserProfiles, _) = Trie.put(userProfiles, callerKey, Principal.equal, profile);
        userProfiles := newUserProfiles;
        
        // Update partner preferences in the partnerPreferences Trie.
        let (newPartnerPreferences, _) = Trie.put(partnerPreferences, callerKey, Principal.equal, preference);
        partnerPreferences := newPartnerPreferences;
        
        // Print debug message indicating successful update of user.
        Debug.print("User updated successfully.");
    };

    // Function to get a user's profile.
    public shared({ caller }) func getUser(userId : Principal) : async ?UserProfile {
        // Print debug message indicating retrieval of user profile.
        Debug.print("Getting user: " # Principal.toText(userId));
        
        // Retrieve user profile from the userProfiles Trie.
        let userKey = { hash = Principal.hash(userId); key = userId };
        Trie.get(userProfiles, userKey, Principal.equal)
    };

    // Function to get a user's partner preferences (shared version).
    public shared({ caller }) func getPreference(userId : Principal) : async ?PartnerPreference {
        // Print debug message indicating retrieval of user's partner preferences.
        Debug.print("Getting preference for user: " # Principal.toText(userId));
        
        // Retrieve partner preferences from the partnerPreferences Trie.
        let userKey = { hash = Principal.hash(userId); key = userId };
        Trie.get(partnerPreferences, userKey, Principal.equal)
    };

    // Function to get a user's partner preferences (query version).
    public query func getPreferenceQuery(userId : Principal) : async ?PartnerPreference {
        // Print debug message indicating retrieval of user's partner preferences.
        Debug.print("Getting preference for user (query): " # Principal.toText(userId));
        
        // Retrieve partner preferences from the partnerPreferences Trie.
        let userKey = { hash = Principal.hash(userId); key = userId };
        Trie.get(partnerPreferences, userKey, Principal.equal)
    };

    // Function to fetch a user's partner preferences asynchronously.
    public shared func fetchPreference(userId : Principal) : async ?PartnerPreference {
        switch (await getPreferenceQuery(userId)) {
            case null {
                // If no preferences found, print debug message and return null.
                Debug.print("No preference found for user: " # Principal.toText(userId));
                return null;
            };
            case (?pref) { return ?pref; }; // Return the preferences.
        }
    };

    // Function to suggest profiles based on a user's partner preferences.
    // Function to suggest profiles based on a user's partner preferences.
    // Function to suggest profiles based on a user's partner preferences.
    public shared({ caller }) func suggestProfiles(userId : Principal) : async [UserProfile] {
        // Print debug message indicating suggestion of profiles for a user.
        Debug.print("Suggesting profiles for user: " # Principal.toText(userId));

        // Fetch the user's preferences asynchronously.
        let preference = await fetchPreference(userId);

        switch (preference) {
            case null {
                // If no preferences found, print debug message and return an empty array.
                Debug.print("No preference found for user: " # Principal.toText(userId));
                return [];
            };
            case (?pref) {
                // If preferences found, iterate through userProfiles Trie to find matching profiles.
                var candidates : [UserProfile] = [];

                // Use Trie.iter to create an iterable collection of the trie's entries
                for (entry in Trie.iter(userProfiles)) {
                    switch (entry) {
                        case (?{ hash = _, key = _ }, ?profile) {
                            // Handle the case where both key and profile have values
                            if (matchPreference(profile, pref)) {
                                candidates := Array.append(candidates, [profile]);
                            }
                        }
                    }
                };


                // Print debug message indicating suggested profiles and return the candidates.
                Debug.print("Suggested profiles: " # debug_show(candidates));
                return candidates;
            };
        }
    };

    // Helper function to check if a profile matches the preferences.
    private func matchPreference(profile : UserProfile, preference : PartnerPreference) : Bool {
        return profile.age >= preference.ageRange.0 and
            profile.age <= preference.ageRange.1 and
            profile.placeOfLiving == preference.placeOfLiving and
            profile.country == preference.country and
            profile.occupation == preference.occupation and
            profile.salary >= preference.salaryRange.0 and
            profile.salary <= preference.salaryRange.1 and
            profile.educationBackground == preference.educationBackground;
    };




}

You have to use a semi-colon when separating fields in a record. You are currently using a comma.

1 Like

I am getting different error

I’m going to assume userProfiles is of type Trie<Principal, UserProfile>.

The key being returned by your iterator of key-value pair is of type Principal not ?Trie.Key<Principal>.

when you call Trie.iter() it returns an iterator of concrete values. They aren’t optional.

so you could do something like this instead:

for ((_, profile) in Trie.iter<Principal,UserProfile>( userProfiles )){

  if (matchPreference(profile, pref)) {
    candidates := Array.append(candidates, [profile])
  }

};

Thank you All, it’s working fine