Skip to content

[BUG][dart-dio] Webhook generation produces invalid import statements with HTML entities #22586

@Lutra-Fs

Description

@Lutra-Fs

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

The dart-dio generator produces invalid Dart import statements when processing OpenAPI specifications that use the webhooks: field (introduced in OpenAPI 3.1). The generated imports use JSON-like template syntax and HTML entity encoding instead of valid Dart import syntax, causing compilation failures.

Actual Output:

import '{import=model.TestNotificationRequest, classname=TestNotificationRequest}';

Expected Output:

import 'package:test_webhook/src/gen/model/test_notification_request.dart';

This issue affects all webhook-based specifications. The generator appears to be using a template variable incorrectly for webhooks, producing template syntax ({import=..., classname=...}) instead of resolved import paths. Additionally, = signs are HTML-encoded as =.

This makes the generated code completely unusable without manual post-processing or workarounds.

openapi-generator version

7.19.0-SNAPSHOT (latest as of 2025-12-29)

OpenAPI declaration file content or url
openapi: 3.1.0
info:
  version: '1.0.0'
  title: Minimal Webhook Test
  description: Minimal spec to reproduce webhook import generation issue
webhooks:
  /TEST_EVENT:
    post:
      tags:
      - Test
      summary: Test Webhook Event
      description: A simple webhook to test import generation
      operationId: testEvent
      security:
      - BasicAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TestNotificationRequest'
      responses:
        '200':
          description: Success
components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
  schemas:
    TestNotificationRequest:
      type: object
      required:
      - eventId
      properties:
        eventId:
          type: string
          description: Unique event identifier
        data:
          type: object
          description: Event payload

This spec has been validated as valid OpenAPI 3.1.0.

Generation Details

CLI Command:

docker run --rm -v "$(pwd):/work" openapitools/openapi-generator-cli:latest generate \
  -g dart-dio \
  -i /work/minimal_webhook_test.yaml \
  -o /work/build/minimal_webhook_test \
  -c /work/tool/codegen/test_config.yaml \
  --reserved-words-mappings="name=name_" \
  --additional-properties="pubName=test_webhook,sourceFolder=src/gen,pubVersion=1.0.0" \
  --global-property=apiDocs=false,modelDocs=false,apiTests=false,modelTests=false

Config file (test_config.yaml):

serializationLibrary: built_value
useEnumExtension: true
enumUnknownDefaultCase: true
Steps to reproduce
  1. Save the minimal spec above as minimal_webhook_test.yaml
  2. Run the generation command shown above
  3. Check the generated file: build/minimal_webhook_test/lib/src/gen/api/test_api.dart
  4. Observe line 11 contains invalid import: import '{import=model.TestNotificationRequest, classname=TestNotificationRequest}';
  5. Attempting to compile the generated Dart code will fail with a syntax error

Generated file excerpt (test_api.dart, lines 1-15):

//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//

import 'dart:async';

import 'package:built_value/json_object.dart';
import 'package:built_value/serializer.dart';
import 'package:dio/dio.dart';

import '{import=model.TestNotificationRequest, classname=TestNotificationRequest}';

class TestApi {
  // ...
}
Related issues/PRs

None

Suggest a fix

The issue appears to be in the Dart Dio generator's template handling for webhook operations. Based on the output, the template is using a mustache variable that resolves to a JSON-like object with import and classname fields, but this is not being properly processed into a valid Dart import string.

Likely root cause:

  • The api.mustache template or a related template in modules/openapi-generator/src/main/resources/dart-dio may have different logic for webhooks vs regular API paths
  • The template variable for import paths (likely import) may be returning a structured object instead of a string path for webhooks
  • HTML entity encoding (==) suggests the template is being double-encoded or processed through an XML/HTML entity encoder

Suggested fix approach:

  1. Check the template files handling webhook generation in modules/openapi-generator/src/main/resources/dart-dio/
  2. Compare the import statement generation logic between regular API paths and webhook paths
  3. Ensure webhook operations use the same import resolution logic as regular API operations
  4. Verify that no HTML entity encoding is applied to Dart code output

Workaround (for users affected):
Post-process the generated files to fix import statements. Here's a shell snippet that can be added to build scripts:

# Fix broken import statements in webhook-generated API files
# Usage: ./fix_webhook_imports.sh <package_name> <output_dir>
# Example: ./fix_webhook_imports.sh my_package ./generated

package_name="${1:-my_package}"
output_dir="${2:-./generated}"

# Find and fix broken imports in webhook-generated API files
find "$output_dir/lib/src/gen" -name "*.dart" -exec grep -l "import '{" {} \; 2>/dev/null | while read file; do
  echo "Processing: $file"
  
  # Extract module name from directory path (e.g., webhook_notification)
  module=$(echo "$file" | sed -E 's|.*/lib/src/gen/([^/]+)/.*|\1|')
  
  # Create temp file for processing
  tmp_file=$(mktemp)
  
  # Process file line by line
  while IFS= read -r line || [[ -n "$line" ]]; do
    if [[ "$line" == "import '{"* ]] && [[ "$line" == *"classname"* ]]; then
      # Extract the class name (handles both = and &#x3D;)
      classname=$(
        echo "$line" \
          | sed -E 's/.*classname(=|&#x3D;)([^}]*)}.*/\2/' \
          | sed 's/&#x3D;//g' \
          | sed 's/&amp;/\&/g'
      )
      
      # Convert CamelCase to snake_case (portable across macOS/Linux)
      # AuthenticationNotificationRequest -> authentication_notification_request
      model_file=$(printf '%s' "$classname" | awk '
        {
          for (i = 1; i <= length($0); i++) {
            c = substr($0, i, 1)
            p = (i > 1) ? substr($0, i - 1, 1) : ""
            n = (i < length($0)) ? substr($0, i + 1, 1) : ""
            if (i > 1 && c ~ /[A-Z]/ && p ~ /[a-z0-9]/) {
              printf "_%s", tolower(c)
            } else if (i > 1 && c ~ /[A-Z]/ && p ~ /[A-Z]/ && n ~ /[a-z]/) {
              printf "_%s", tolower(c)
            } else {
              printf "%s", tolower(c)
            }
          }
        }
      ')
      
      # Generate the correct import
      echo "import 'package:${package_name}/src/gen/${module}/model/${model_file}.dart';"
    else
      echo "$line"
    fi
  done < "$file" > "$tmp_file"
  
  # Replace the original file
  mv "$tmp_file" "$file"
done

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions