Skip to content

Improve safety and clarity in getProducer to handle unnamed response properties#971

Merged
marina-p merged 1 commit intomicrosoft:mainfrom
landoncrabtree:landoncrabtree-patch-1
Aug 21, 2025
Merged

Improve safety and clarity in getProducer to handle unnamed response properties#971
marina-p merged 1 commit intomicrosoft:mainfrom
landoncrabtree:landoncrabtree-patch-1

Conversation

@landoncrabtree
Copy link
Contributor

If response entries in a Swagger spec are arrays (and not objects), then when attempting to compile via Restler compile --api_spec, it will throw an error:

ERROR: Compiler failed. See logs in Compile directory for more information.

Task Compile failed.
Collecting logs...

With the following error logs,

Unhandled exception. System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.)
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at Restler.Dependencies.visitLeaf2@869.Invoke(FSharpList`1 parentAccessPath, LeafProperty p) in C:\restler-fuzzer\src\compiler\Restler.Compiler\Dependencies.fs:line 897
   at Restler.Grammar.Tree.iterCtx[a,LeafData,INodeData](FSharpFunc`2 fLeaf, FSharpFunc`2 fNode, FSharpFunc`2 fCtx, a ctx, Tree`2 tree) in C:\restler-fuzzer\src\compiler\Restler.Compiler\Grammar.fs:line 60
   at Restler.Grammar.Tree.recurse@57-1.Invoke(a ctx, Tree`2 tree)
   at Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc`2 action, IEnumerable`1 source) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\seq.fs:line 497
   at Restler.Grammar.Tree.iterCtx[a,LeafData,INodeData](FSharpFunc`2 fLeaf, FSharpFunc`2 fNode, FSharpFunc`2 fCtx, a ctx, Tree`2 tree) in C:\restler-fuzzer\src\compiler\Restler.Compiler\Grammar.fs:line 63
   at Restler.Grammar.Tree.recurse@57-1.Invoke(a ctx, Tree`2 tree)
   at Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc`2 action, IEnumerable`1 source) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\seq.fs:line 497
   at Restler.Grammar.Tree.iterCtx[a,LeafData,INodeData](FSharpFunc`2 fLeaf, FSharpFunc`2 fNode, FSharpFunc`2 fCtx, a ctx, Tree`2 tree) in C:\restler-fuzzer\src\compiler\Restler.Compiler\Grammar.fs:line 63
   at Restler.Dependencies.getProducer(RequestId request, Tree`2 response) in C:\restler-fuzzer\src\compiler\Restler.Compiler\Dependencies.fs:line 907
   at Restler.Dependencies.extractDependencies@1286.Invoke(Tuple`2 tupledArg) in C:\restler-fuzzer\src\compiler\Restler.Compiler\Dependencies.fs:line 1290
   at Microsoft.FSharp.Collections.ArrayModule.Parallel.Iterate@1334.Invoke(Int32 i) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\array.fs:line 1334
   at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.<ForWorker>b__1(RangeWorker& currentWorker, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`2.<ForWorker>b__1(RangeWorker& currentWorker, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
   at System.Threading.Tasks.TaskReplicator.Replica.Execute()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.TaskReplicator.Run[TState](ReplicatableUserAction`1 action, ParallelOptions options, Boolean stopOnFirstFailure)
   at System.Threading.Tasks.Parallel.ForWorker[TLocal,TInt](TInt fromInclusive, TInt toExclusive, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Func`4 bodyWithLocal, Func`1 localInit, Action`1 localFinally)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Parallel.ForWorker[TLocal,TInt](TInt fromInclusive, TInt toExclusive, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Func`4 bodyWithLocal, Func`1 localInit, Action`1 localFinally)
   at System.Threading.Tasks.Parallel.For(Int32 fromInclusive, Int32 toExclusive, Action`1 body)
   at Microsoft.FSharp.Collections.ArrayModule.Parallel.Iterate[T](FSharpFunc`2 action, T[] array) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\array.fs:line 1334
   at Restler.Dependencies.extractDependencies(Tuple`2[] requestData, IEnumerable`1 globalAnnotations, MutationsDictionary customDictionary, Boolean queryDependencies, Boolean bodyDependencies, Boolean headerDependencies, Boolean allowGetProducers, Boolean dataFuzzing, FSharpMap`2 perResourceDictionaries, FSharpOption`1 namingConvention) in C:\restler-fuzzer\src\compiler\Restler.Compiler\Dependencies.fs:line 1280
   at Restler.Compiler.Main.generateRequestGrammar(FSharpList`1 swaggerDocs, MutationsDictionary dictionary, Config config, FSharpList`1 globalExternalAnnotations, FSharpList`1 userSpecifiedExamples) in C:\restler-fuzzer\src\compiler\Restler.Compiler\Compiler.fs:line 1421
   at Restler.Workflow.generateGrammarFromSwagger(String grammarOutputDirectoryPath, Config config) in C:\restler-fuzzer\src\compiler\Restler.Compiler\Workflow.fs:line 143
   at Restler.Workflow.generateRestlerGrammar(Config config) in C:\restler-fuzzer\src\compiler\Restler.Compiler\Workflow.fs:line 250
   at Program.main(String[] argv) in C:\restler-fuzzer\src\compiler\Restler.CompilerExe\Program.fs:line 43

Here is a simple Swagger spec to reproduce the issue:

{
  "swagger": "2.0",
  "info": { "version": "1.0.0", "title": "PoC API" },
  "paths": {
    "/api/do-something": {
      "get": {
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "array",
              "items": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}

The proposed changes add better safety handling in the case there is no top-level object (e.g. nested arrays), where .name could be null. This prevents NullReferenceException, however, it still does not implement the actual producer logic: TODO: support cases where the entire response is an array

…properties

This change refactors the `getProducer` function to improve safety and maintainability:

Ensures name.Value is only accessed after confirming name.IsSome, preventing potential NullReferenceExceptions when response properties are unnamed.

Improves DEBUG logging to provide clearer diagnostics when unnamed properties are encountered.

These improvements reduce the chance of runtime errors when parsing Swagger specs with unnamed or array-based responses and make future debugging and maintenance easier.
@landoncrabtree
Copy link
Contributor Author

@microsoft-github-policy-service agree company="Microsoft"

Copy link
Contributor

@marina-p marina-p left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@marina-p marina-p merged commit 405f7e3 into microsoft:main Aug 21, 2025
9 checks passed
@marina-p
Copy link
Contributor

Thank you for the improvements!


In reply to: 3138655697

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants