Plumber: Deploy failure with dynamic routes (if @param same as function arg)

Created on 4 Jun 2018  路  7Comments  路  Source: rstudio/plumber

I found the if the parameter name in the @param field is the same as the one in the dynamic route (e.g. @param mypar1 and then @get /prediction/<mypar1> and then function(mypar1)), plumber fails on p$run() with the error:

Error in if (type == "bool" || type == "logical") { : 
missing value where TRUE/FALSE needed 

This is not the case for non-dynamic routes, and can be fixed by changing the @param to anything else.

Example below. Full code can be found at this repository.

library(plumber)

# @param ticket; @get /prediction; function(ticket)... 
p1 <- plumb("not_dyn_samenames.R")

# Works:
p1$run(port=8001)

# @param tick; @get /prediction/<ticket>; function(ticket)...
p2 <- plumb("dyn_diffnames.R")

# Works
p2$run(port=8002)

# @param ticket; @get /prediction/<ticket>; function(ticket)...
p3 <- plumb("dyn_samenames.R")

# DOES NOT WORK
p3$run(port=8003)
intermediate low help wanted medium swagger bug

Most helpful comment

The problem occurs in extractSwaggerParams (swagger.R):

  for (p in names(endpointParams)){
    location <- "query"
    if (p %in% pathParams$name){
      location <- "path"
    }

    type <- endpointParams[[p]]$type
    if (is.null(type) || is.na(type)){
      if (location == "path") {
        type <- plumberToSwaggerType(pathParams[pathParams$name == p,"type"])
      } else {
        type <- "string" # Default to string
      }
    }

If the @param field and dynamic route have the same name, location will be set to path, and an attempt is made to run plumberToSwaggerType but this fails because type is NA.

If the @param field and dynamic routes have different names location will be query, and type will be defaulted to string.

If someone wants to check for reproducibility, this is the definition for dyn_samenames.R :

#* Retrieve prediction for ticket
#* @param ticket Ticket number to retrieve
#* @get /prediction/<ticket>
#* @json
function(ticket){

  list(ticket = ticket,
       prediction = as.Date(Sys.time()))
}

and then run it as:

p <- plumb("dyn_samenames.R")
p$run(port=8888)

All 7 comments

We had a similar error for a roughly similar scenario, but I just tried now and cannot replicate your DOES NOT WORK scenario I am afraid. Such a not so useful error message.

OK I will see if I can isolate the problem. In the mean time, here is my session info.

(I updated all packages today as well, still the same error)

R version 3.5.0 (2018-04-23)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

Matrix products: default

locale:
[1] LC_COLLATE=English_Australia.1252  LC_CTYPE=English_Australia.1252   
[3] LC_MONETARY=English_Australia.1252 LC_NUMERIC=C                      
[5] LC_TIME=English_Australia.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] plumber_0.4.6

loaded via a namespace (and not attached):
 [1] compiler_3.5.0 magrittr_1.5   R6_2.2.2       promises_1.0.1 later_0.7.2    tools_3.5.0   
 [7] rstudioapi_0.7 Rcpp_0.12.17   crayon_1.3.4   stringi_1.2.2  jsonlite_1.5   httpuv_1.4.3

The problem occurs in extractSwaggerParams (swagger.R):

  for (p in names(endpointParams)){
    location <- "query"
    if (p %in% pathParams$name){
      location <- "path"
    }

    type <- endpointParams[[p]]$type
    if (is.null(type) || is.na(type)){
      if (location == "path") {
        type <- plumberToSwaggerType(pathParams[pathParams$name == p,"type"])
      } else {
        type <- "string" # Default to string
      }
    }

If the @param field and dynamic route have the same name, location will be set to path, and an attempt is made to run plumberToSwaggerType but this fails because type is NA.

If the @param field and dynamic routes have different names location will be query, and type will be defaulted to string.

If someone wants to check for reproducibility, this is the definition for dyn_samenames.R :

#* Retrieve prediction for ticket
#* @param ticket Ticket number to retrieve
#* @get /prediction/<ticket>
#* @json
function(ticket){

  list(ticket = ticket,
       prediction = as.Date(Sys.time()))
}

and then run it as:

p <- plumb("dyn_samenames.R")
p$run(port=8888)

Right! My bad, having suffered from exactly the same error, you are right:

  1. IF params$name == dynamicRoute$name && !type ERROR
  2. IF params$name == dynamicRoute$name && type SUCCESS.

Is @param value meant to be processed?

I cannot do a PR, you should kindly do it @RemkoDuursma

Similar to #273

I believe this is fixed in master branch.

Running reprex above...

Can get

~: curl http://127.0.0.1:8888/prediction/3
{"ticket":["3"],"prediction":["2019-07-11"]}

and have swagger info of

鉂澂 p$swaggerFile() %>% jsonlite::toJSON(pretty = TRUE)
{
  "openapi": ["3.0.2"],
  "info": {
    "description": ["API Description"],
    "title": ["API Title"],
    "version": ["1.0.0"]
  },
  "paths": {
    "/prediction/{ticket}": {
      "get": {
        "summary": [" Retrieve prediction for ticket"],
        "responses": {
          "default": {
            "description": ["Default response."]
          }
        },
        "parameters": [
          {
            "name": ["ticket"],
            "description": ["Ticket number to retrieve"],
            "in": ["path"],
            "required": [true],
            "schema": {
              "type": ["string"]
            }
          }
        ]
      }
    },
    "/openapi.json": {
      "get": {
        "responses": {
          "default": {
            "description": ["Default response."]
          }
        },
        "parameters": []
      }
    },
    "/swagger.json": {
      "get": {
        "responses": {
          "default": {
            "description": ["Default response."]
          }
        },
        "parameters": []
      }
    },
    "/__swagger__/index.html": {
      "get": {
        "responses": {
          "default": {
            "description": ["Default response."]
          }
        },
        "parameters": []
      }
    },
    "/__swagger__/": {
      "get": {
        "responses": {
          "default": {
            "description": ["Default response."]
          }
        },
        "parameters": []
      }
    }
  }
} 

Please submit a new issue if the problem still exists.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

elbamos picture elbamos  路  6Comments

colearendt picture colearendt  路  4Comments

Amalabdu picture Amalabdu  路  6Comments

david-cortes picture david-cortes  路  3Comments

alexzaytsev-newsroomly picture alexzaytsev-newsroomly  路  6Comments