sdk-codegen icon indicating copy to clipboard operation
sdk-codegen copied to clipboard

TypeScript SDK run_inline_query() format type of PNG/JPG causing 500 error

Open ps-fcaraballo opened this issue 4 years ago • 2 comments
trafficstars

Im using the TypeScript SDK to export the data of a simple looker table in 4 different formats:

  • JSON
  • CSV
  • PNG
  • JPG

Here is the code, the main function that grabs that data is the following, FetchQuery():

async function FetchQuery(params: {
      dashboard: {
        element?: IDashboardElement;
        // Provided by Looker API - Dashboard Filters
        filters?: IDashboardFilter[];
    };
    // Provided by User - Current State of User's Filters.
    userFilters?: Dict<any>;
    options: {
        sort?: string[];
        cache?: boolean;
        format?: string;
    };
}): Promise<string | undefined> {
    const {dashboard, options, userFilters} = params;
    const {element, filters} = dashboard;
    if (element?.query?.model === undefined || element?.query?.view === undefined) {
        throw new Error("Fetch Query contains either no model or view!");
    }
    const results = await sdk.ok(
        sdk.run_inline_query(
            {
                body: {
                    model: element?.query?.model,
                    view: element?.query?.view,
                    fields: element?.query?.fields,
                    sorts: options?.sort ?? element?.query?.sorts ?? [],
                    limit: element?.query?.limit,
                    filters: BuildInlineQueryFilters(filters, element?.query?.filters, userFilters),
                    vis_config: {type: "looker_grid"},
                },
                result_format: options?.format ?? "json_detail",
                generate_drill_links: true,
                apply_formatting: true,
                apply_vis: true,
                cache: options?.cache ?? false,
                cache_only: false,
            },
            {timeout: 30},
        ),
    );
    return results;
}

I also added FetchTileTables() to show how FetchQuery() is used!

export async function FetchTileTables(params: {
    dashboard?: {elements?: IDashboardElement[]; filters?: IDashboardFilter[]};
    filters?: Filter[];
    userFilters?: Dict<any>;
    options?: {
        sort?: string[][];
        cache?: boolean;
        format?: string;
    };
}): Promise<Tile[] | undefined> {
    const {dashboard, filters, options, userFilters} = params;
    if (dashboard?.elements) {
        const queries: any[] = await Promise.all(
            dashboard?.elements.map((element, index) =>
                FetchQuery({
                    dashboard: {element, filters: dashboard?.filters},
                    userFilters,
                    options: {
                        sort: options?.sort !== undefined ? options?.sort[index] : undefined,
                        cache: options?.cache,
                        format: options?.format,
                    },
                }),
            ),
        );
     ............
}

The dashboard is a simple looker table that max's out at 500 rows. The dashboard data always comes back in the correct format in both CSV & JSON formats but PNG/JPG. The same exact body is used for each call here in the first function (fetchQuery):

    const result = sdk.run_inline_query({
                body: {
                    model: element?.query?.model,
                    view: element?.query?.view,
                    fields: element?.query?.fields,
                    sorts: options?.sort ?? element?.query?.sorts ?? [],
                    limit: element?.query?.limit,
                    filters: BuildInlineQueryFilters(filters, element?.query?.filters, userFilters),
                    vis_config: {type: "looker_grid"},
                },
                result_format: options?.format ?? "json_detail",
                generate_drill_links: true,
                apply_formatting: true,
                apply_vis: true,
                cache: options?.cache ?? false,
                cache_only: false,
            },
            {timeout: 30},
        ),
    )

if you notice one of the lines contains the result_format: result_format: options?.format ?? "json_detail"

The only thing to change with each SDK call is the options?.format, so the following formats returns result as a non 500 error:

  • options?.format == csv, 200 with the correct data
  • options?.format == json_detail, 200 with the correct data
  • options?.format == jpg, 500 with the error Error: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received undefined.
  • options?.format == png, 500 with the error Error: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received undefined.

Has anyone seen this issue or experienced similar problem?

ps-fcaraballo avatar Apr 06 '21 23:04 ps-fcaraballo

Also sorry for the lack of new lines in the code, for reason I couldn't the new lines to show in the code block

ps-fcaraballo avatar Apr 06 '21 23:04 ps-fcaraballo

@ps-fcaraballo what version of @looker/sdk are you using? can you reproduce the issue by hardcoding the SDK call in your code with explicit arguments inside your FetchQuery method? e.g.

        sdk.run_inline_query(
            {
                body: {
                    model: 'mymodel',
                    view: 'myview'
                    fields: ['field1'],
                    ...
                },
                result_format: 'png',
                generate_drill_links: true,
                apply_formatting: true,
                apply_vis: true,
                cache: false,
                cache_only: false,
            },
            {timeout: 30},
        ),
    );

joeldodge79 avatar Apr 08 '21 13:04 joeldodge79