gRPC `fixed64` wrong conversion

  • Goal: I need to access a gRPC service that takes a fixed64 field in a request message.

  • Steps:

  1. Build and deploy gRPC server that echos both a fixed64 and int32 number
  2. Add the gRPC service as gRPC resource
  3. Build an app that posts a constant value and show the result from the service
  • Details: No code or error messages are shown. With grpcurl I get the correct results:
$ grpcurl -plaintext -d '{"number": "17034143211355898120"}' retoolfixed64-nlb-7bc75fe38f59a2ab.elb.eu-west-1.amazonaws.com:50051 protos.HelloService/HelloFixed64
{
  "number": "17034143211355898120"
}

You see the input equals the output.

  • Screenshots:

Screenshot 2025-01-22 at 11.56.09

Here you see the echo'ed result is wrong.

I'm a new user so I can't upload an attachment. The JSON of a clean and simple app is below.

JSON export ```json {"uuid":"336c3388-d8ad-11ef-b7ce-c790ad5f2dec","page":{"id":366951618,"data":{"appState":"[\"~#iR\",[\"^ \",\"n\",\"appTemplate\",\"v\",[\"^ \",\"appMaxWidth\",\"100%\",\"appStyles\",\"\",\"appTesting\",null,\"appThemeId\",null,\"appThemeModeId\",null,\"appThemeName\",null,\"createdAt\",null,\"customComponentCollections\",[],\"customDocumentTitle\",\"\",\"customDocumentTitleEnabled\",false,\"customShortcuts\",[],\"experimentalDataTabEnabled\",true,\"experimentalFeatures\",[\"^ \",\"disableMultiplayerEditing\",false,\"multiplayerEditingEnabled\",false,\"sourceControlTemplateDehydration\",false],\"folders\",[\"~#iL\",[]],\"formAppSettings\",[\"^ \",\"customRedirectUrl\",\"\"],\"inAppRetoolPillAppearance\",\"NO_OVERRIDE\",\"instrumentationEnabled\",false,\"internationalizationSettings\",[\"^ \",\"internationalizationEnabled\",false,\"internationalizationFiles\",[]],\"isFetching\",false,\"isFormApp\",false,\"isGlobalWidget\",false,\"isMobileApp\",false,\"loadingIndicatorsDisabled\",false,\"markdownLinkBehavior\",\"auto\",\"mobileAppSettings\",[\"^ \",\"displaySetting\",[\"^ \",\"landscapeMode\",false,\"tabletMode\",false],\"mobileOfflineModeBannerMode\",\"default\",\"mobileOfflineModeDelaySync\",false,\"mobileOfflineModeEnabled\",false],\"mobileOfflineAssets\",[],\"multiScreenMobileApp\",false,\"notificationsSettings\",[\"^ \",\"globalQueryShowFailureToast\",true,\"globalQueryShowSuccessToast\",false,\"globalQueryToastDuration\",4.5,\"globalToastPosition\",\"bottomRight\"],\"pageCodeFolders\",[\"^ \"],\"pageLoadValueOverrides\",[\"^B\",[]],\"plugins\",[\"~#iOM\",[\"query1\",[\"^0\",[\"^ \",\"n\",\"pluginTemplate\",\"v\",[\"^ \",\"id\",\"query1\",\"uuid\",null,\"type\",\"datasource\",\"subtype\",\"GRPCQuery\",\"namespace\",null,\"resourceName\",\"18efe18b-45c0-416d-ada3-82e5e2ef8497\",\"resourceDisplayName\",\"Fixed64 test\",\"template\",[\"^15\",[\"queryRefreshTime\",\"\",\"serviceName\",\"protos.HelloService\",\"allowedGroupIds\",[\"^B\",[]],\"streamResponse\",false,\"lastReceivedFromResourceAt\",null,\"queryDisabledMessage\",\"\",\"servedFromCache\",false,\"offlineUserQueryInputs\",\"\",\"successMessage\",\"\",\"queryDisabled\",\"\",\"playgroundQuerySaveId\",\"latest\",\"workflowParams\",null,\"resourceNameOverride\",\"\",\"runWhenModelUpdates\",true,\"showFailureToaster\",true,\"query\",\"{\\n \\\"number\\\": {{ textInput1.value }}\\n}\",\"playgroundQueryUuid\",\"\",\"playgroundQueryId\",null,\"error\",null,\"workflowRunBodyType\",\"raw\",\"privateParams\",[\"^B\",[]],\"queryRunOnSelectorUpdate\",false,\"runWhenPageLoadsDelay\",\"\",\"data\",null,\"methodName\",\"HelloFixed64\",\"importedQueryInputs\",[\"^15\",[]],\"isImported\",false,\"showSuccessToaster\",true,\"cacheKeyTtl\",\"\",\"requestSentTimestamp\",null,\"metadata\",null,\"queryRunTime\",null,\"changesetObject\",\"\",\"offlineOptimisticResponse\",null,\"errorTransformer\",\"return data.error\",\"finished\",null,\"confirmationMessage\",null,\"isFetching\",false,\"changeset\",\"\",\"rawData\",null,\"queryTriggerDelay\",\"0\",\"resourceTypeOverride\",null,\"watchedParams\",[\"^B\",[]],\"enableErrorTransformer\",false,\"isHidden\",false,\"showLatestVersionUpdatedWarning\",false,\"timestamp\",0,\"importedQueryDefaults\",[\"^15\",[]],\"enableTransformer\",true,\"showUpdateSetValueDynamicallyToggle\",true,\"overrideOrgCacheForUserCache\",false,\"runWhenPageLoads\",false,\"transformer\",\"return data\",\"events\",null,\"queryTimeout\",\"10000\",\"workflowId\",null,\"requireConfirmation\",false,\"queryFailureConditions\",\"\",\"changesetIsObject\",false,\"enableCaching\",false,\"allowedGroups\",[\"^B\",[]],\"offlineQueryType\",\"None\",\"queryThrottleTime\",\"750\",\"updateSetValueDynamically\",false,\"notificationDuration\",\"\"]],\"style\",null,\"position2\",null,\"mobilePosition2\",null,\"mobileAppPosition\",null,\"tabIndex\",null,\"container\",\"\",\"^7\",\"~m1737542453353\",\"updatedAt\",\"~m1737542914639\",\"folder\",\"\",\"screen\",null]]],\"$main\",[\"^0\",[\"^ \",\"n\",\"pluginTemplate\",\"v\",[\"^ \",\"id\",\"$main\",\"^16\",null,\"^17\",\"frame\",\"^18\",\"Frame\",\"^19\",null,\"^1:\",null,\"^1;\",null,\"^1<\",[\"^15\",[\"type\",\"main\",\"sticky\",null,\"padding\",\"8px 12px\",\"enableFullBleed\",false,\"isHiddenOnDesktop\",false,\"isHiddenOnMobile\",false]],\"^1=\",[\"^15\",[]],\"^1>\",null,\"^1?\",null,\"^1@\",null,\"^1A\",null,\"^1B\",\"\",\"^7\",\"~m1737542857160\",\"^1C\",\"~m1737542857160\",\"^1D\",\"\",\"^1E\",null]]],\"textInput1\",[\"^0\",[\"^ \",\"n\",\"pluginTemplate\",\"v\",[\"^ \",\"id\",\"textInput1\",\"^16\",\"9025a951-c0ac-4fa5-903a-6dab15d0783f\",\"^17\",\"widget\",\"^18\",\"TextInputWidget2\",\"^19\",null,\"^1:\",null,\"^1;\",null,\"^1<\",[\"^15\",[\"spellCheck\",false,\"readOnly\",false,\"iconAfter\",\"\",\"showCharacterCount\",false,\"autoComplete\",false,\"enforceMaxLength\",false,\"maxLength\",null,\"hidden\",false,\"customValidation\",\"\",\"patternType\",\"\",\"hideValidationMessage\",false,\"textBefore\",\"\",\"validationMessage\",\"\",\"margin\",\"4px 8px\",\"textAfter\",\"\",\"showInEditor\",false,\"showClear\",false,\"pattern\",\"\",\"tooltipText\",\"\",\"labelAlign\",\"left\",\"formDataKey\",\"{{ self.id }}\",\"value\",\"16034143211355898120\",\"labelCaption\",\"\",\"labelWidth\",\"33\",\"autoFill\",\"\",\"placeholder\",\"Enter value\",\"label\",\"Input\",\"_validate\",false,\"labelWidthUnit\",\"%\",\"invalid\",false,\"iconBefore\",\"\",\"minLength\",null,\"inputTooltip\",\"\",\"events\",[\"^15\",[]],\"autoCapitalize\",\"none\",\"loading\",false,\"disabled\",false,\"labelPosition\",\"top\",\"labelWrap\",false,\"maintainSpaceWhenHidden\",false,\"required\",false]],\"^1=\",[\"^15\",[]],\"^1>\",[\"^0\",[\"^ \",\"n\",\"position2\",\"v\",[\"^ \",\"^17\",\"grid\",\"^1B\",\"\",\"rowGroup\",\"body\",\"subcontainer\",\"\",\"row\",0,\"col\",0,\"height\",0.2,\"width\",4,\"tabNum\",0,\"stackPosition\",null]]],\"^1?\",null,\"^1@\",null,\"^1A\",null,\"^1B\",\"\",\"^7\",\"~m1737542871137\",\"^1C\",\"~m1737542997509\",\"^1D\",\"\",\"^1E\",null]]],\"text1\",[\"^0\",[\"^ \",\"n\",\"pluginTemplate\",\"v\",[\"^ \",\"id\",\"text1\",\"^16\",\"7e9d1163-3a95-4658-8b4f-ab45f8345941\",\"^17\",\"widget\",\"^18\",\"TextWidget2\",\"^19\",null,\"^1:\",null,\"^1;\",null,\"^1<\",[\"^15\",[\"heightType\",\"auto\",\"horizontalAlign\",\"left\",\"hidden\",false,\"imageWidth\",\"fit\",\"margin\",\"4px 8px\",\"showInEditor\",false,\"verticalAlign\",\"center\",\"tooltipText\",\"\",\"value\",\"Echo: {{ query1.data?.number }}\",\"disableMarkdown\",false,\"overflowType\",\"scroll\",\"maintainSpaceWhenHidden\",false]],\"^1=\",[\"^15\",[]],\"^1>\",[\"^0\",[\"^ \",\"n\",\"position2\",\"v\",[\"^ \",\"^17\",\"grid\",\"^1B\",\"\",\"^1F\",\"body\",\"^1G\",\"\",\"row\",1.8,\"col\",0,\"^1H\",1,\"^1I\",3,\"^1J\",0,\"^1K\",null]]],\"^1?\",null,\"^1@\",null,\"^1A\",null,\"^1B\",\"\",\"^7\",\"~m1737542922957\",\"^1C\",\"~m1737542989807\",\"^1D\",\"\",\"^1E\",null]]]]],\"preloadedAppJavaScript\",null,\"preloadedAppJSLinks\",[],\"queryStatusVisibility\",false,\"responsiveLayoutDisabled\",false,\"rootScreen\",null,\"savePlatform\",\"web\",\"shortlink\",null,\"testEntities\",[],\"tests\",[],\"urlFragmentDefinitions\",[\"^B\",[]],\"version\",\"3.139.0\"]]]"},"changesRecord":[{"type":"WIDGET_TEMPLATE_UPDATE","payload":{"plugin":{"id":"textInput1","type":"widget","uuid":"9025a951-c0ac-4fa5-903a-6dab15d0783f","style":{},"folder":"","subtype":"TextInputWidget2","template":{"label":"Label","value":"16034143211355898120","events":{},"hidden":false,"margin":"4px 8px","invalid":false,"loading":false,"pattern":"","autoFill":"","disabled":false,"readOnly":false,"required":false,"_validate":false,"iconAfter":"","labelWrap":false,"maxLength":null,"minLength":null,"showClear":false,"textAfter":"","iconBefore":"","labelAlign":"left","labelWidth":"33","spellCheck":false,"textBefore":"","formDataKey":"{{ self.id }}","patternType":"","placeholder":"Enter value","tooltipText":"","autoComplete":false,"inputTooltip":"","labelCaption":"","showInEditor":false,"labelPosition":"top","autoCapitalize":"none","labelWidthUnit":"%","customValidation":"","enforceMaxLength":false,"validationMessage":"","showCharacterCount":false,"hideValidationMessage":false,"maintainSpaceWhenHidden":false},"container":"","createdAt":"2025-01-22T10:47:51.137Z","position2":{"col":0,"row":0,"type":"grid","width":4,"height":0.2,"tabNum":0,"rowGroup":"body","container":"","subcontainer":"","stackPosition":null},"updatedAt":"2025-01-22T10:47:57.627Z"},"update":{"label":"Input"},"widgetId":"textInput1","shouldRecalculateTemplate":true},"isUserTriggered":true}],"changesRecordV2":[{"data":{"op":"update","ids":["textInput1"],"tag":"plugin"},"type":"diff","version":1}],"gitSha":null,"checksum":null,"createdAt":"2025-01-22T10:49:59.760Z","updatedAt":"2025-01-22T10:49:59.760Z","pageId":3846188,"userId":61790},"modules":{}} ```

I managed to work-around this issue by using gRPC gateway which exposes the gRPC service as HTTP.

Thanks for sharing your workaround, @jtti

We have a bug report on file where some users have experienced gRPC resources in Retool converting strings to integers, I wonder if that is the issue :thinking: I can reach out if our team ships a fix for that bug!

Yeah it might be related; 64-bit integers (fixed64, uint64, int64) must be encoded as JSON strings because of constraints in JavaScript. It looks like something is off when Retool converts that to the protobuf wire format.

1 Like