Malformed Order Error

https://bessapay.net/errors/malformed-order

Overview

A Malformed Order error occurs when an order request contains invalid, incomplete, or inconsistent data. This error is more specific than a general validation error as it relates specifically to order processing and business logic issues in order data.

Details

  • Error Code: MALFORMED_ORDER
  • HTTP Status: 400
  • Error Type: Client Error

Common scenarios

  • • Inconsistent line items or quantities
  • • Invalid product combinations
  • • Incomplete shipping or billing information
  • • Order total calculation mismatches
  • • Invalid discount codes or promotions

Example

Malformed Order Error Response
1{
2  "type": "https://bessapay.net/errors/malformed-order",
3  "title": "Malformed Order",
4  "status": 400,
5  "detail": "Order contains products that cannot be shipped to the provided address",
6  "instance": "/api/v1/orders",
7  "errorCode": "MALFORMED_ORDER",
8  "timestamp": "2023-06-15T20:30:45Z",
9  "issues": [
10    {
11      "code": "SHIPPING_RESTRICTION",
12      "message": "Product 'PRD-123' cannot be shipped to country 'AU'",
13      "affectedItems": ["PRD-123"]
14    },
15    {
16      "code": "INVALID_COMBINATION",
17      "message": "Products 'PRD-456' and 'PRD-789' cannot be ordered together",
18      "affectedItems": ["PRD-456", "PRD-789"]
19    }
20  ]
21}

How to Handle

Check order data integrity

Ensure that all required order fields are present and correctly formatted. Verify that product IDs, quantities, and pricing information are accurate.

Validate product combinations

Some products cannot be ordered together due to shipping restrictions, compatibility issues, or business rules. Implement client-side validation to prevent incompatible combinations.

Verify regional availability

Check if products can be shipped to the customer's address before allowing them to be added to the cart. Consider implementing region-specific product filtering.

Handle issues individually

The error response includes an issues array with specific problems. Process each issue individually and present clear messages to the user about what needs to be fixed.

Handling Order Issues
1// Example of processing individual order issues
2function processOrderIssues(errorData) {
3  // Check if we have specific issues to process
4  if (errorData.issues && Array.isArray(errorData.issues)) {
5    const issuesByType = {
6      SHIPPING_RESTRICTION: [],
7      INVENTORY_ISSUE: [],
8      PRICING_ISSUE: [],
9      INVALID_COMBINATION: [],
10      OTHER: []
11    };
12    
13    // Group issues by type
14    errorData.issues.forEach(issue => {
15      if (issuesByType[issue.code]) {
16        issuesByType[issue.code].push(issue);
17      } else {
18        issuesByType.OTHER.push(issue);
19      }
20    });
21    
22    // Handle shipping restrictions
23    if (issuesByType.SHIPPING_RESTRICTION.length > 0) {
24      handleShippingRestrictions(issuesByType.SHIPPING_RESTRICTION);
25    }
26    
27    // Handle invalid product combinations
28    if (issuesByType.INVALID_COMBINATION.length > 0) {
29      handleInvalidCombinations(issuesByType.INVALID_COMBINATION);
30    }
31    
32    // Handle inventory issues
33    if (issuesByType.INVENTORY_ISSUE.length > 0) {
34      handleInventoryIssues(issuesByType.INVENTORY_ISSUE);
35    }
36    
37    // Return true if we handled any specific issues
38    return Object.values(issuesByType).some(issues => issues.length > 0);
39  }
40  
41  // No specific issues to handle
42  return false;
43}

Re-validate on changes

After a user makes changes to fix order issues, re-validate the entire order to ensure no new issues have been introduced.

Code Example: Order Validation and Submission

Order Validation and Error Handling
1// Complete example of order validation and submission
2class OrderService {
3  constructor(apiKey, baseUrl = 'https://api.semuni.com/v1') {
4    this.apiKey = apiKey;
5    this.baseUrl = baseUrl;
6  }
7  
8  // Validate an order before submission
9  async validateOrder(orderData) {
10    try {
11      const response = await fetch(`${this.baseUrl}/orders/validate`, {
12        method: 'POST',
13        headers: {
14          'Authorization': `Bearer ${this.apiKey}`,
15          'Content-Type': 'application/json'
16        },
17        body: JSON.stringify(orderData)
18      });
19      
20      if (!response.ok) {
21        const errorData = await response.json();
22        
23        if (errorData.type === 'https://bessapay.net/errors/malformed-order') {
24          return {
25            valid: false,
26            errors: errorData.issues || [],
27            message: errorData.detail
28          };
29        }
30        
31        throw new Error(errorData.detail || 'Order validation failed');
32      }
33      
34      return {
35        valid: true
36      };
37    } catch (error) {
38      console.error('Order validation error:', error);
39      throw error;
40    }
41  }
42  
43  // Submit an order with pre-validation
44  async submitOrder(orderData) {
45    try {
46      // First validate the order
47      const validation = await this.validateOrder(orderData);
48      
49      if (!validation.valid) {
50        return {
51          success: false,
52          stage: 'validation',
53          errors: validation.errors,
54          message: validation.message
55        };
56      }
57      
58      // If validation passed, submit the order
59      const response = await fetch(`${this.baseUrl}/orders`, {
60        method: 'POST',
61        headers: {
62          'Authorization': `Bearer ${this.apiKey}`,
63          'Content-Type': 'application/json'
64        },
65        body: JSON.stringify(orderData)
66      });
67      
68      if (!response.ok) {
69        const errorData = await response.json();
70        
71        // Check if it's a malformed order that passed validation but failed on submission
72        if (errorData.type === 'https://bessapay.net/errors/malformed-order') {
73          return {
74            success: false,
75            stage: 'submission',
76            errors: errorData.issues || [],
77            message: errorData.detail
78          };
79        }
80        
81        throw new Error(errorData.detail || 'Order submission failed');
82      }
83      
84      const orderResult = await response.json();
85      
86      return {
87        success: true,
88        order: orderResult
89      };
90    } catch (error) {
91      console.error('Order submission error:', error);
92      return {
93        success: false,
94        stage: 'system',
95        message: 'An unexpected error occurred. Please try again.'
96      };
97    }
98  }
99  
100  // Helper method to fix common order issues
101  fixOrderIssues(orderData, issues) {
102    const fixedOrder = { ...orderData };
103    
104    issues.forEach(issue => {
105      switch (issue.code) {
106        case 'SHIPPING_RESTRICTION':
107          // Remove products that can't be shipped
108          if (issue.affectedItems && fixedOrder.items) {
109            fixedOrder.items = fixedOrder.items.filter(item => 
110              !issue.affectedItems.includes(item.productId)
111            );
112          }
113          break;
114          
115        case 'INVALID_COMBINATION':
116          // If we have invalid combinations, keep only the first item in each combination
117          if (issue.affectedItems && fixedOrder.items) {
118            const firstItemToKeep = issue.affectedItems[0];
119            fixedOrder.items = fixedOrder.items.filter(item => 
120              item.productId === firstItemToKeep || !issue.affectedItems.includes(item.productId)
121            );
122          }
123          break;
124          
125        // Add more issue handlers as needed
126      }
127    });
128    
129    return fixedOrder;
130  }
131}
132
133// Usage example
134const orderService = new OrderService('your-api-key');
135
136// Submit an order
137async function placeOrder(orderData) {
138  try {
139    const result = await orderService.submitOrder(orderData);
140    
141    if (!result.success) {
142      // Show errors to the user
143      displayOrderErrors(result.errors, result.message);
144      
145      // If we can automatically fix some issues, offer that option
146      if (result.errors && result.errors.length > 0) {
147        const fixedOrder = orderService.fixOrderIssues(orderData, result.errors);
148        
149        if (fixedOrder.items.length !== orderData.items.length) {
150          offerFixedOrder(fixedOrder);
151        }
152      }
153      
154      return null;
155    }
156    
157    // Success! Show confirmation
158    showOrderConfirmation(result.order);
159    return result.order;
160  } catch (error) {
161    console.error('Error placing order:', error);
162    showGenericError('We encountered a problem while processing your order. Please try again.');
163    return null;
164  }
165}