Help

422 error creating linked record via API

1681 0
cancel
Showing results for 
Search instead for 
Did you mean: 
Edward1976
6 - Interface Innovator
6 - Interface Innovator

I have a Lambda function which is trying to create records in an Image Assets table. One of the fields (Race Name) is a linked record to another table in my base. This table is also synced to another base. The code seems to successfully find the Race name from within this other base using the record_id but there is something preventing it being created and I can't work out what it is? Here is my code

import axios from 'axios';

// Utility function to get random stage
const getRandomStage = () => {
  const stages = ['DISCOVERY', 'REMIND', 'OFFER', 'FINAL OFFER'];
  return stages[Math.floor(Math.random() * stages.length)];
};

const createImageAssetRecords = async (baseId, tableName, airtableApiKey, raceName, recordId, imageNum) => {
  const platforms = ['Etsy', 'Pinterest', 'FB Image Post', 'IG Image Post', '1080x1920'];
  const airtableUrl = `https://api.airtable.com/v0/${baseId}/${encodeURIComponent(tableName)}`;

  const createRecordPromises = platforms.map(async (platform) => {
    const newRecord = {
      fields: {
        'Stage': getRandomStage(),
        'Race Name': raceName, // Use the raceName value instead of the recordId
        'unique_url_id': `${raceName}-PBPOSTERS-${new Date().toISOString().slice(0, 10)}_${recordId}`,
        'Image Num': imageNum,
        'Platform': platform,
      },
    };

    return axios.post(airtableUrl, { records: [newRecord] }, {
      headers: {
        'Authorization': `Bearer ${airtableApiKey}`,
        'Content-Type': 'application/json'
      }
    });
  });

  return Promise.all(createRecordPromises);
};

export const handler = async (event, context) => {
  try {
    const s3Event = event.Records[0].s3;
    const objectKey = s3Event.object.key;
    const bucketName = s3Event.bucket.name;

    if (bucketName !== 'pbposters-images' || !objectKey.startsWith('output/')) {
      console.log(`Ignoring object ${objectKey} in bucket ${bucketName} because it's not in the "pbposters-images" bucket or not in the "output" folder.`);
      return context.succeed();
    }

    const regex = /(?:output\/)?(rec\w+)(?=_\d+_img)/;
    const matches = regex.exec(objectKey);
    if (!matches) {
      console.log(`Cannot extract record ID from ${objectKey}`);
      return context.succeed();
    }
    const recordId = matches[1];
    const airtableApiKey = 'MYKEY';
    const originalBaseId = 'appm793Ym1yyUPzjR';
    const syncedBaseId = 'apptVrueL0miLrJez';
    const racesTableName = 'Races';
    const imageAssetsTableName = 'Image Assets';

    // Get the race associated with the record ID from the original base
    const recordUrl = `https://api.airtable.com/v0/${originalBaseId}/${encodeURIComponent(racesTableName)}/${recordId}`;
    const recordResponse = await axios.get(recordUrl, {
      headers: {
        'Authorization': `Bearer ${airtableApiKey}`
      }
    });

    const raceName = recordResponse.data.fields['Race Name'];

    // Extract image number from object key
    const imageNumRegex = /_(\d+)_img/;
    const imageNumMatch = imageNumRegex.exec(objectKey);
    const imageNum = imageNumMatch ? imageNumMatch[1] : '';

    // Create image asset records in the synced base
    await createImageAssetRecords(syncedBaseId, imageAssetsTableName, airtableApiKey, raceName, recordId, imageNum);

    context.succeed();
  } catch (error) {
    console.error('Error processing S3 event:', error);
    context.fail();
  }
};

And here is part of the error log:

2023-04-07T15:42:44.252Z d4c3cb71-fcf0-4c82-9744-0c0e4d7a2230 ERROR Error processing S3 event: AxiosError: Request failed with status code 422
at settle (file:///opt/nodejs/node_modules/axios/lib/core/settle.js:19:12)
at IncomingMessage.handleStreamEnd (file:///opt/nodejs/node_modules/axios/lib/adapters/http.js:556:11)
at IncomingMessage.emit (node:events:525:35)
at endReadableNT (node:internal/streams/readable:1359:12)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
code: 'ERR_BAD_REQUEST',
config: {
transitional: {
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false
},
adapter: [ 'xhr', 'http' ],
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: { FormData: [Function], Blob: [class Blob] },
validateStatus: [Function: validateStatus],
headers: AxiosHeaders {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
Authorization: 'Bearer pateoroUjBhfRuxSv.78c0a9d58e302c381520c1e97930fb5d026a8dbdfb538d1f5d06b3283464d1ef',
'User-Agent': 'axios/1.3.4',
'Content-Length': '208',
'Accept-Encoding': 'gzip, compress, deflate, br'
},
method: 'post',
url: 'https://api.airtable.com/v0/apptVrueL0miLrJez/Image%20Assets',
data: '{"records":[{"fields":{"Stage":"FINAL OFFER","Race Name":"Ultraman Arizona","unique_url_id":"Ultraman Arizona-PBPOSTERS-2023-04-07_recSGs5tDfV4Nccs8","Image Num":"2","Platform":"Pinterest"},"typecast":true}]}'
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype] {
abort: [Function (anonymous)],
aborted: [Function (anonymous)],
connect: [Function (anonymous)],
error: [Function (anonymous)],
socket: [Function (anonymous)],
timeout: [Function (anonymous)],
finish: [Function: requestOnFinish]
},
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
strictContentLength: false,
_contentLength: '208',
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: false,
socket: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
secureConnecting: false,
_SNICallback: null,
servername: 'api.airtable.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 10,
connecting: false,
_hadError: false,
_parent: null,
_host: 'api.airtable.com',
_closeAfterHandlingError: false,
_readableState: [ReadableState],
_maxListeners: undefined,
_writableState: [WritableState],
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: [TLSWrap],
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular *1],
[Symbol(res)]: [TLSWrap],
[Symbol(verified)]: true,
[Symbol(pendingSession)]: null,
[Symbol(async_id_symbol)]: 294,
[Symbol(kHandle)]: [TLSWrap],
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kSetNoDelay)]: false,
[Symbol(kSetKeepAlive)]: true,
[Symbol(kSetKeepAliveInitialDelay)]: 60,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(connect-options)]: [Object]
},
_header: 'POST /v0/apptVrueL0miLrJez/Image%20Assets HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'Content-Type: application/json\r\n' +
'Authorization: Bearer pateoroUjBhfRuxSv.78c0a9d58e302c381520c1e97930fb5d026a8dbdfb538d1f5d06b3283464d1ef\r\n' +
'User-Agent: axios/1.3.4\r\n' +
'Content-Length: 208\r\n' +
'Accept-Encoding: gzip, compress, deflate, br\r\n' +
'Host: api.airtable.com\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: Agent {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
defaultPort: 443,
protocol: 'https:',
options: [Object: null prototype],
requests: [Object: null prototype] {},
sockets: [Object: null prototype],
freeSockets: [Object: null prototype] {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
scheduling: 'lifo',
maxTotalSockets: Infinity,
totalSocketCount: 5,
maxCachedSessions: 100,
_sessionCache: [Object],
[Symbol(kCapture)]: false
},
socketPath: undefined,
method: 'POST',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: '/v0/apptVrueL0miLrJez/Image%20Assets',
_ended: true,
res: IncomingMessage {
_readableState: [ReadableState],
_events: [Object: null prototype],
_eventsCount: 4,
_maxListeners: undefined,
socket: [TLSSocket],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
rawHeaders: [Array],
rawTrailers: [],
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 422,
statusMessage: 'Unprocessable Entity',
client: [TLSSocket],
_consuming: false,
_dumped: false,
req: [Circular *1],
responseUrl: 'https://api.airtable.com/v0/apptVrueL0miLrJez/Image%20Assets',
redirects: [],
[Symbol(kCapture)]: false,
[Symbol(kHeaders)]: [Object],
[Symbol(kHeadersCount)]: 32,
[Symbol(kTrailers)]: null,
[Symbol(kTrailersCount)]: 0
},
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'api.airtable.com',
protocol: 'https:',
_redirectable: Writable {
_writableState: [WritableState],
_events: [Object: null prototype],
_eventsCount: 3,
_maxListeners: undefined,
_options: [Object],
_ended: true,
_ending: true,
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 208,
_requestBodyBuffers: [],
_onNativeResponse: [Function (anonymous)],
_currentRequest: [Circular *1],
_currentUrl: 'https://api.airtable.com/v0/apptVrueL0miLrJez/Image%20Assets',
[Symbol(kCapture)]: false
},
[Symbol(kCapture)]: false,
[Symbol(kBytesWritten)]: 0,
[Symbol(kEndCalled)]: true,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype] {
accept: [Array],
'content-type': [Array],
authorization: [Array],
'user-agent': [Array],
'content-length': [Array],
'accept-encoding': [Array],
host: [Array]
},
[Symbol(errored)]: null,
[Symbol(kUniqueHeaders)]: null
},
response: {
status: 422,
statusText: 'Unprocessable Entity',
headers: AxiosHeaders {
date: 'Fri, 07 Apr 2023 15:42:44 GMT',
'content-type': 'application/json; charset=utf-8',
'content-length': '127',
connection: 'close',
'set-cookie': [Array],
server: 'Tengine',
'strict-transport-security': 'max-age=31536000; includeSubDomains; preload',
'access-control-allow-origin': '*',
'access-control-allow-methods': 'DELETE,GET,OPTIONS,PATCH,POST,PUT',
'access-control-allow-headers': 'authorization,content-length,content-type,user-agent,x-airtable-application-id,x-airtable-user-agent,x-api-version,x-requested-with',
'x-frame-options': 'DENY',
'x-content-type-options': 'nosniff',
etag: 'W/"7f-ic7Ppjtti07fW0oQKWhpH6lrz8A"',
vary: 'Accept-Encoding'
},
config: {
transitional: [Object],
adapter: [Array],
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: [Object],
validateStatus: [Function: validateStatus],
headers: [AxiosHeaders],
method: 'post',
url: 'https://api.airtable.com/v0/apptVrueL0miLrJez/Image%20Assets',
data: '{"records":[{"fields":{"Stage":"FINAL OFFER","Race Name":"Ultraman Arizona","unique_url_id":"Ultraman Arizona-PBPOSTERS-2023-04-07_recSGs5tDfV4Nccs8","Image Num":"2","Platform":"Pinterest"},"typecast":true}]}'
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype],
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
strictContentLength: false,
_contentLength: '208',
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: false,
socket: [TLSSocket],
_header: 'POST /v0/apptVrueL0miLrJez/Image%20Assets HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'Content-Type: application/json\r\n' +
'Authorization: Bearer pateoroUjBhfRuxSv.78c0a9d58e302c381520c1e97930fb5d026a8dbdfb538d1f5d06b3283464d1ef\r\n' +
'User-Agent: axios/1.3.4\r\n' +
'Content-Length: 208\r\n' +
'Accept-Encoding: gzip, compress, deflate, br\r\n' +
'Host: api.airtable.com\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: [Agent],
socketPath: undefined,
method: 'POST',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: '/v0/apptVrueL0miLrJez/Image%20Assets',
_ended: true,
res: [IncomingMessage],
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'api.airtable.com',
protocol: 'https:',
_redirectable: [Writable],
[Symbol(kCapture)]: false,
[Symbol(kBytesWritten)]: 0,
[Symbol(kEndCalled)]: true,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype],
[Symbol(errored)]: null,
[Symbol(kUniqueHeaders)]: null
},
data: { error: [Object] }
}
}

Any help much appreciated as been trying to work this out for days!

 

0 Replies 0